API Reference

The Oncade Server API lets you manage account linking, products, wallets and purchases from your game servers. All requests require HTTPS and include authentication headers.

NOTE: we also provide the Oncade API Test Dashboard. You can try out requests live at Oncade API Test Dashboard.

Common headers

Every request must include the Authorization header with Bearer <your_api_key> and X-Oncade-API-Version (defaults to v1). Game endpoints require X-Game-Id with a server API key. Campaign endpoints (/v1/campaign/...) require X-Campaign-Id with a campaign API key. For POST and PUT requests, supply an Idempotency-Key to safely retry requests without creating duplicates.

Get GameGET

/v1/game

Fetch game details for the game associated with the API key.

curl -X GET https://oncade.gg/api/v1/game \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "gameId": "test-game",
  "name": "Test Game",
  "description": "An awesome test game",
  "imageUrl": "https://example.com/image.png",
  "smallImageUrl": "https://example.com/small.png",
  "storeImageUrl": "https://example.com/store.png",
  "demoUrl": "https://example.com/demo",
  "steamAppId": "12345",
  "discordUrl": "https://discord.gg/test",
  "screenshots": [
    "https://example.com/ss1.png",
    "https://example.com/ss2.png"
  ],
  "status": "approved",
  "environment": "test",
  "affiliateRate": 10,
  "enableTip": true,
  "isVisible": true,
  "createdAt": "2024-01-01T00:00:00.000Z",
  "updatedAt": "2024-01-02T00:00:00.000Z"
}

Create Virtual CurrencyPOST

/v1/vc/currencies

Define a virtual currency for your game. Requires an Idempotency-Key header.

curl -X POST https://oncade.gg/api/v1/vc/currencies \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 6a03c211-2804-43ef-8fa8-49f28f93cec8" \
  -H "Content-Type: application/json" \
  -d '{
  "code": "GEM",
  "name": "Gems",
  "baseUnitsPerVcUnit": "100",
  "centralWalletAddress": "wallet-placeholder"
}'

Example Response

{
  "currency": {
    "_id": "cur_123",
    "code": "GEM",
    "name": "Gems",
    "status": "active",
    "baseUnitsPerVcUnit": "100",
    "centralWalletAddress": "wallet-placeholder"
  }
}

List Virtual CurrenciesGET

/v1/vc/currencies

Return paginated virtual currencies for the authenticated game.

curl -X GET https://oncade.gg/api/v1/vc/currencies?page=1&limit=20 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "items": [
    {
      "_id": "cur_123",
      "code": "GEM",
      "name": "Gems",
      "status": "active",
      "baseUnitsPerVcUnit": "100",
      "centralWalletAddress": "wallet-placeholder"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "totalCount": 1,
    "totalPages": 1,
    "hasNextPage": false,
    "hasPrevPage": false
  }
}

Update Virtual CurrencyPATCH

/v1/vc/currencies/{currencyId}

Update currency fields. All body params are optional.

curl -X PATCH https://oncade.gg/api/v1/vc/currencies/cur_123 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Get User BalanceGET

/v1/vc/balances

Fetch a player balance for the specified currency.

curl -X GET https://oncade.gg/api/v1/vc/balances?currencyId=cur_123&userRef=link_usr_abc \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "currencyId": "cur_123",
  "userRef": "link_usr_abc",
  "balanceUnits": "500",
  "updatedAt": "2024-05-01T00:00:00.000Z"
}

List Journal EntriesGET

/v1/vc/journals

Return paginated ledger entries for a player and currency. Results are sorted newest-first.

curl -X GET https://oncade.gg/api/v1/vc/journals?currencyId=cur_123&userRef=link_usr_abc \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "items": [
    {
      "_id": "jrnl_001",
      "type": "credit",
      "postings": [
        {
          "account": {
            "type": "pool",
            "address": "wallet-placeholder"
          },
          "deltaUnits": "-500"
        },
        {
          "account": {
            "type": "user",
            "userRef": "link_usr_abc"
          },
          "deltaUnits": "500"
        }
      ],
      "createdAt": "2024-05-01T00:00:00.000Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 50,
    "totalCount": 1,
    "totalPages": 1,
    "hasNextPage": false,
    "hasPrevPage": false
  }
}

Credit Player BalancePOST

/v1/vc/credits

Move units from the treasury into a player balance. Returns 201 with a journal entry.

curl -X POST https://oncade.gg/api/v1/vc/credits \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: fff40e4f-6f96-4ab5-8cb3-5df0830a5b01" \
  -H "Content-Type: application/json" \
  -d '{
  "currencyId": "cur_123",
  "userRef": "link_usr_abc",
  "amountUnits": "500",
  "orderId": "order-123"
}'

Example Response

{
  "journalId": "jrnl_002",
  "newBalanceUnits": "1500",
  "breakdown": [
    {
      "participant": "pool",
      "direction": "debit",
      "amountUnits": "500",
      "description": "Credit to user"
    },
    {
      "participant": "user",
      "direction": "credit",
      "userRef": "link_usr_abc",
      "amountUnits": "500",
      "description": "Credit to user"
    }
  ]
}

Debit Player BalancePOST

/v1/vc/debits

Remove units from a player balance and return them to the treasury. Returns 201 with a journal entry.

curl -X POST https://oncade.gg/api/v1/vc/debits \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 6dff2497-cbad-4171-984b-d25e045b89ac" \
  -H "Content-Type: application/json" \
  -d '{
  "currencyId": "cur_123",
  "userRef": "link_usr_abc",
  "amountUnits": "250",
  "reason": "refund"
}'

Example Response

{
  "journalId": "jrnl_003",
  "newBalanceUnits": "1250",
  "breakdown": [
    {
      "participant": "user",
      "direction": "debit",
      "userRef": "link_usr_abc",
      "amountUnits": "250",
      "description": "Refund"
    },
    {
      "participant": "pool",
      "direction": "credit",
      "amountUnits": "250",
      "description": "Refund"
    }
  ]
}

Batch Debit with DistributionPOST

/v1/vc/batch

Atomically debit one player and distribute to multiple recipients. All-or-nothing — the total is the sum of recipient amounts.

curl -X POST https://oncade.gg/api/v1/vc/batch \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 15303970-7316-4f9b-bfdf-6384a00c4b53" \
  -H "Content-Type: application/json" \
  -d '{
  "currencyId": "cur_123",
  "sourceUserRef": "link_usr_player1",
  "recipients": "[\n  {\n    \"userRef\": \"link_usr_winner1\",\n    \"amountUnits\": \"100\",\n    \"description\": \"First place\"\n  },\n  {\n    \"userRef\": \"link_usr_winner2\",\n    \"amountUnits\": \"50\",\n    \"description\": \"Second place\"\n  },\n  {\n    \"toPool\": true,\n    \"amountUnits\": \"25\",\n    \"description\": \"Pool contribution\"\n  },\n  {\n    \"toPool\": true,\n    \"amountUnits\": \"25\",\n    \"description\": \"Game wallet fee\"\n  }\n]"
}'

Example Response

{
  "journalId": "jrnl_batch_001",
  "newBalanceUnits": "800",
  "breakdown": [
    {
      "participant": "user",
      "direction": "debit",
      "userRef": "link_usr_player1",
      "amountUnits": "200",
      "description": "Batch transaction debit"
    },
    {
      "participant": "user",
      "direction": "credit",
      "userRef": "link_usr_winner1",
      "amountUnits": "100",
      "description": "First place"
    },
    {
      "participant": "user",
      "direction": "credit",
      "userRef": "link_usr_winner2",
      "amountUnits": "50",
      "description": "Second place"
    },
    {
      "participant": "pool",
      "direction": "credit",
      "amountUnits": "25",
      "description": "Pool contribution"
    },
    {
      "participant": "pool",
      "direction": "credit",
      "amountUnits": "25",
      "description": "Game wallet fee"
    }
  ]
}

Create Cashout RequestPOST

/v1/vc/cashouts

Stage a cashout for manual review. Balance is not debited until approval. Returns 201.

curl -X POST https://oncade.gg/api/v1/vc/cashouts \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 2ca93670-c82e-4924-90b8-3d1ce7954b96" \
  -H "Content-Type: application/json" \
  -d '{
  "currencyId": "cur_123",
  "userRef": "link_usr_abc",
  "units": "2000"
}'

Example Response

{
  "cashoutRequestId": "co_001"
}

List Cashout RequestsGET

/v1/vc/cashouts

Return cashout requests with pagination. Filter by status or user.

curl -X GET https://oncade.gg/api/v1/vc/cashouts?currencyId=cur_123&status=pendingReview&page=1&limit=20 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "items": [
    {
      "_id": "co_001",
      "userRef": "link_usr_abc",
      "unitsRequested": "2000",
      "status": "pendingReview",
      "requestedRate": {
        "baseUnitsPerVcUnit": "100",
        "capturedAt": "2024-05-01T00:00:00.000Z"
      }
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "totalCount": 1,
    "totalPages": 1,
    "hasNextPage": false,
    "hasPrevPage": false
  }
}

Approve Cashout RequestPOST

/v1/vc/cashouts/{cashoutRequestId}/approve

Approve and execute a cashout. Debits the requested units and records a conversion.

curl -X POST https://oncade.gg/api/v1/vc/cashouts/co_001/approve \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: cb3a2134-ec56-4ca9-8398-b0c5e06dd90f"

Example Response

{
  "transactionId": "jrnl_convert_1",
  "usedBaseUnitsPerVcUnit": "100",
  "convertedBaseUnits": "200000"
}

Reject Cashout RequestPOST

/v1/vc/cashouts/{cashoutRequestId}/reject

Reject a pending cashout request. Returns 204.

curl -X POST https://oncade.gg/api/v1/vc/cashouts/co_001/reject \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 0a51678f-5a2a-43ab-8cfa-58d186fdb191" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "KYC pending"
}'

Get CampaignGET

/v1/campaign/{campaignId}

Fetch campaign details, status, and balances.

curl -X GET https://oncade.gg/api/v1/campaign/cmp_demo \
  -H "Authorization: Bearer CAMPAIGN_API_KEY" \
  -H "X-Campaign-Id: CAMPAIGN_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "success": true,
  "campaign": {
    "id": "cmp_demo",
    "name": "My Campaign",
    "environment": "test",
    "status": "started",
    "businessId": "65fa1234abcdef5678901234",
    "address": "0xabcDEFabcDEFabcDEFabcDEFabcDEFabcDEFabcd",
    "createdAt": "2025-09-01T12:34:56.789Z",
    "updatedAt": "2025-09-01T12:34:56.789Z",
    "totalAmountFunded": 0,
    "totalAmountPaidOut": 0,
    "availableToWithdraw": 0
  }
}

Start CampaignPUT

/v1/campaign/{campaignId}/start

Activate the campaign. Returns 202 and enqueues a background job.

curl -X PUT https://oncade.gg/api/v1/campaign/cmp_demo/start \
  -H "Authorization: Bearer CAMPAIGN_API_KEY" \
  -H "X-Campaign-Id: CAMPAIGN_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 3ba94c4d-15d3-4fb3-93a0-94262b55012d"

Example Response

{
  "success": true,
  "message": "Start enqueued"
}

Stop CampaignPUT

/v1/campaign/{campaignId}/stop

Stop the campaign. Returns 202 and enqueues a background job.

curl -X PUT https://oncade.gg/api/v1/campaign/cmp_demo/stop \
  -H "Authorization: Bearer CAMPAIGN_API_KEY" \
  -H "X-Campaign-Id: CAMPAIGN_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: f8bb5bd7-24a4-4979-b45a-3591b0cd38d4"

Example Response

{
  "success": true,
  "message": "Stop enqueued"
}

Enqueue Campaign EventPOST

/v1/campaign/{campaignId}/events

Record a campaign event for a linked user. Returns 202.

curl -X POST https://oncade.gg/api/v1/campaign/cmp_demo/events \
  -H "Authorization: Bearer CAMPAIGN_API_KEY" \
  -H "X-Campaign-Id: CAMPAIGN_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 8c9b3fe8-1397-4e59-94ff-887c2017cc1d" \
  -H "Content-Type: application/json" \
  -d '{
  "eventCode": "quest_complete",
  "userRef": "link_usr_123"
}'

Example Response

{
  "success": true,
  "message": "Event enqueued"
}

List Campaign EventsGET

/v1/campaign/{campaignId}/events

Return configured campaign events.

curl -X GET https://oncade.gg/api/v1/campaign/cmp_demo/events \
  -H "Authorization: Bearer CAMPAIGN_API_KEY" \
  -H "X-Campaign-Id: CAMPAIGN_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "success": true,
  "events": [
    {
      "code": "quest_complete",
      "name": "Quest Complete",
      "payoutAmount": 1000
    }
  ]
}

Withdraw Campaign FundsPOST

/v1/campaign/{campaignId}/withdraw

Withdraw remaining funds from a stopped campaign. Returns 202.

curl -X POST https://oncade.gg/api/v1/campaign/cmp_demo/withdraw \
  -H "Authorization: Bearer CAMPAIGN_API_KEY" \
  -H "X-Campaign-Id: CAMPAIGN_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 55aa8b2c-98c0-434a-91bb-4e54266fb0e6"

Example Response

{
  "success": true,
  "message": "Withdrawal enqueued"
}

Get Campaign User DetailsGET

/v1/campaign/{campaignId}/user/{userId}

Fetch a user's status within a campaign.

curl -X GET https://oncade.gg/api/v1/campaign/cmp_demo/user/user_123 \
  -H "Authorization: Bearer CAMPAIGN_API_KEY" \
  -H "X-Campaign-Id: CAMPAIGN_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "success": true,
  "data": {
    "campaignId": "cmp_demo",
    "userId": "user_123",
    "status": "started",
    "environment": "test"
  }
}

Get Campaign User EventsGET

/v1/campaign/{campaignId}/user/{userId}/events

Fetch paginated event history for a user in a campaign.

curl -X GET https://oncade.gg/api/v1/campaign/cmp_demo/user/user_123/events?limit=10&offset=0 \
  -H "Authorization: Bearer CAMPAIGN_API_KEY" \
  -H "X-Campaign-Id: CAMPAIGN_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "success": true,
  "data": {
    "campaignId": "cmp_demo",
    "userId": "user_123",
    "environment": "test",
    "transactions": [
      {
        "id": "507f1f77bcf86cd799439011",
        "campaignId": "cmp_demo",
        "userRef": "user_123",
        "eventCode": "quest_complete",
        "eventName": "Quest Complete",
        "payoutAmount": 1000,
        "transactionHash": "0xabc123def456...",
        "createdAt": "2025-10-01T14:30:00.000Z"
      }
    ],
    "pagination": {
      "limit": 10,
      "offset": 0,
      "total": 1,
      "hasMore": false
    }
  }
}

Get User PurchasesGET

/v1/users/{userRef}/purchases

List purchase history for a user.

curl -X GET https://oncade.gg/api/v1/users/user_123/purchases?limit=10&offset=20&type=subscription \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

[
  {
    "itemId": "507f1f77bcf86cd799439011",
    "gameId": "game_123",
    "createdAt": "2024-03-10T14:12:01.123Z",
    "item": {
      "name": "Founders Pass",
      "type": "subscription",
      "price": 1299
    }
  }
]

Get User InfoGET

/v1/users/{userRef}

Fetch profile information for a user.

curl -X GET https://oncade.gg/api/v1/users/user_123 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "userRef": "user_123",
  "email": "player@example.com",
  "profileImageUrl": "https://cdn.example.com/u/123.png",
  "subscriptions": [
    {
      "itemId": "item_456",
      "status": "Active",
      "subscriptionId": "sub_123",
      "planCode": "PREMIUM_MONTHLY",
      "planId": "plan_abc"
    }
  ]
}

Get User SubscriptionsGET

/v1/users/{userRef}/subscriptions

Fetch all subscriptions for a user.

curl -X GET https://oncade.gg/api/v1/users/user_123/subscriptions \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "subscriptions": [
    {
      "itemId": "item_456",
      "status": "Active",
      "subscriptionId": "sub_123",
      "planCode": "PREMIUM_MONTHLY",
      "planId": "plan_abc"
    },
    {
      "itemId": "item_789",
      "status": "Canceled",
      "subscriptionId": "sub_456",
      "planCode": "BASIC_YEARLY",
      "planId": "plan_xyz"
    }
  ]
}

Get Subscription by ItemGET

/v1/users/{userRef}/subscriptions/{itemId}

Fetch a specific subscription for a user by item ID.

curl -X GET https://oncade.gg/api/v1/users/user_123/subscriptions/item_456 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "itemId": "item_456",
  "status": "Active",
  "subscriptionId": "sub_123",
  "planCode": "PREMIUM_MONTHLY",
  "planId": "plan_abc"
}

Cancel SubscriptionPOST

/v1/users/{userRef}/subscriptions/{itemId}/cancel

Cancel an active subscription. Works for guest accounts too. Dispatches Subscription.Canceled.

curl -X POST https://oncade.gg/api/v1/users/user_abc123/subscriptions/6565fade4f0d5f25af0a9ab3/cancel \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: d0db8026-dacf-44ad-a372-d86d4870eba2"

Example Response

{
  "success": true,
  "subscriptionId": "sub_123"
}

List ProductsGET

/v1/products

List products for the game. Supports filtering by status, type, creator, or keyword.

curl -X GET https://oncade.gg/api/v1/products?status=active&type=purchase&q=sword&page=1&limit=20 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "products": [
    {
      "_id": "64b10b1cec13f995e9000011",
      "gameId": "game_123",
      "environment": "test",
      "type": "purchase",
      "name": "Sword of Testing",
      "description": "Legendary blade for QA heroes.",
      "price": 100,
      "fulfillmentType": "NONE",
      "isVisible": true,
      "createdAt": "2024-01-01T00:00:00.000Z",
      "updatedAt": "2024-01-01T00:00:00.000Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "totalCount": 1,
    "totalPages": 1,
    "hasNextPage": false,
    "hasPrevPage": false
  }
}

Get ProductGET

/v1/product/{productId}

Fetch a single product by ID.

curl -X GET https://oncade.gg/api/v1/product/64b10b1cec13f995e9000011 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "_id": "64b10b1cec13f995e9000011",
  "gameId": "game_123",
  "environment": "test",
  "type": "purchase",
  "name": "Sword of Testing",
  "description": "Legendary blade for QA heroes.",
  "baseGameRequirementText": "Requires the free base game to play.",
  "price": 100,
  "fulfillmentType": "NONE",
  "isVisible": true,
  "createdAt": "2024-01-01T00:00:00.000Z",
  "updatedAt": "2024-01-01T00:00:00.000Z"
}

Create Product (SDK)POST

/v1/product

Create a product from your game server. Accepts USD and/or virtual currency pricing. Returns 201.

curl -X POST https://oncade.gg/api/v1/product \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 6544d325-d0b7-41ab-bbe9-258ba3f1b783" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Premium Sword",
  "type": "purchase",
  "fulfillmentType": "WEBHOOK",
  "description": "A legendary blade",
  "baseGameRequirementText": "Requires the free base game to play.",
  "price": 1500,
  "virtualCurrencyPrices": "[\n  {\n    \"currencyId\": \"cur_123\",\n    \"amount\": 100\n  }\n]",
  "perUserLimit": 1,
  "metadata": {
    "rarity": "legendary"
  }
}'

Example Response

{
  "_id": "65fa1234abcdef5678901234",
  "gameId": "game_123",
  "environment": "test",
  "type": "purchase",
  "name": "Premium Sword",
  "description": "A legendary blade",
  "baseGameRequirementText": "Requires the free base game to play.",
  "price": 1500,
  "hasUsdPrice": true,
  "virtualCurrencyPrices": [
    {
      "currencyId": "cur_123",
      "amount": 100,
      "currency": {
        "code": "GEM",
        "name": "Gems"
      }
    }
  ],
  "fulfillmentType": "WEBHOOK",
  "isVisible": true,
  "isPriceVisible": true,
  "forSale": true,
  "perUserLimit": 1,
  "status": "active",
  "creatorType": "game",
  "createdAt": "2024-01-01T00:00:00.000Z",
  "updatedAt": "2024-01-01T00:00:00.000Z"
}

Update Product (SDK)PATCH

/v1/product/{productId}

Update an existing product. All fields are optional.

curl -X PATCH https://oncade.gg/api/v1/product/65fa1234abcdef5678901234 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -d '{
  "name": "Premium Sword v2",
  "baseGameRequirementText": "Requires the free base game to play.",
  "price": 1200,
  "virtualCurrencyPrices": "[\n  {\n    \"currencyId\": \"cur_123\",\n    \"amount\": 80\n  }\n]",
  "forSale": "true"
}'

Example Response

{
  "_id": "65fa1234abcdef5678901234",
  "gameId": "game_123",
  "environment": "test",
  "type": "purchase",
  "name": "Premium Sword v2",
  "description": "A legendary blade",
  "baseGameRequirementText": "Requires the free base game to play.",
  "price": 1200,
  "hasUsdPrice": true,
  "virtualCurrencyPrices": [
    {
      "currencyId": "cur_123",
      "amount": 80,
      "currency": {
        "code": "GEM",
        "name": "Gems"
      }
    }
  ],
  "fulfillmentType": "WEBHOOK",
  "isVisible": true,
  "isPriceVisible": true,
  "forSale": true,
  "perUserLimit": 1,
  "status": "active",
  "createdAt": "2024-01-01T00:00:00.000Z",
  "updatedAt": "2024-01-02T00:00:00.000Z"
}

Create ProductPOST

/v1/products

Create a product for the game. Returns 201.

curl -X POST https://oncade.gg/api/v1/products \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 2e222667-7c25-4e03-8399-bf70e11ffe37" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Test Weapon",
  "type": "purchase",
  "fulfillmentType": "WEBHOOK",
  "description": "A test weapon created from the frontend",
  "price": 1500,
  "imageUrl": "https://cdn.example.com/items/test-weapon.png",
  "perUserLimit": 2,
  "purchaseDisplayInfo": "purchase_count",
  "metadata": {
    "rarity": "legendary"
  }
}'

Example Response

{
  "_id": "65fa1234abcdef5678901234",
  "gameId": "game_123",
  "environment": "test",
  "type": "purchase",
  "name": "Test Weapon",
  "description": "A test weapon created from the frontend",
  "price": 1500,
  "fulfillmentType": "WEBHOOK",
  "isVisible": true,
  "isPriceVisible": true,
  "forSale": true,
  "createdAt": "2024-01-01T00:00:00.000Z",
  "updatedAt": "2024-01-01T00:00:00.000Z"
}

Update Product Sale StatePUT

/v1/products

Enable or disable sales for an existing product.

curl -X PUT https://oncade.gg/api/v1/products \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 41126066-6e60-4dad-97b3-d11142955847" \
  -H "Content-Type: application/json" \
  -d '{
  "productId": "507f1f77bcf86cd799439011",
  "forSale": "true"
}'

Example Response

{
  "_id": "507f1f77bcf86cd799439011",
  "gameId": "game_123",
  "environment": "test",
  "type": "purchase",
  "name": "Sword of Dawn",
  "price": 1500,
  "forSale": true,
  "fulfillmentType": "WEBHOOK"
}

Create UGC ProductPOST

/v1/products/{userRef}

Create a user-generated product. Created as a hidden draft with sales disabled. Returns 201.

curl -X POST https://oncade.gg/api/v1/products/link_usr_123 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 10690217-1517-4c77-8904-34c27422424b" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "User Created Armor",
  "type": "purchase",
  "fulfillmentType": "WEBHOOK",
  "description": "Custom armor created by user",
  "price": 2000,
  "metadata": {
    "rarity": "legendary"
  },
  "imageUrl": "https://cdn.example.com/items/ugc-armor.png",
  "perUserLimit": 1
}'

Example Response

{
  "_id": "65fa1234abcdef5678901234",
  "gameId": "game_123",
  "environment": "test",
  "type": "purchase",
  "creatorType": "ugc",
  "status": "draft",
  "name": "User Created Armor",
  "description": "Custom armor created by user",
  "price": 2000,
  "imageUrl": "https://cdn.example.com/items/ugc-armor.png",
  "metadata": {
    "rarity": "legendary",
    "idempotencyKey": "ugc-armor-20240501"
  },
  "perUserLimit": 1,
  "isVisible": false,
  "isPriceVisible": true,
  "forSale": false,
  "createdAt": "2024-04-22T18:07:43.123Z",
  "updatedAt": "2024-04-22T18:07:43.123Z",
  "fulfillmentType": "WEBHOOK"
}

Submit Product for ReviewPOST

/v1/products/{userRef}/{productId}/submit

Submit a user-generated product for admin review.

curl -X POST https://oncade.gg/api/v1/products/user_123/product_1/submit \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 120ea080-fa8a-4486-92e4-920d94e09cc7"

Review ProductPOST

/v1/products/{userRef}/{productId}/review

Approve or decline a submitted product. On approval, you can override pricing and display settings.

curl -X POST https://oncade.gg/api/v1/products/user_123/product_1/review \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: a9ae5ad1-9930-4da0-a632-332465add5f0" \
  -H "Content-Type: application/json" \
  -d '{
  "decision": "approve",
  "isVisible": "true",
  "forSale": "true",
  "price": 1500,
  "virtualCurrencyPrices": "[\n  {\n    \"currencyId\": \"cur_123\",\n    \"amount\": 100\n  }\n]"
}'

Example Response

{
  "_id": "65fa1234abcdef5678901234",
  "gameId": "game_123",
  "environment": "test",
  "type": "purchase",
  "creatorType": "ugc",
  "status": "active",
  "name": "User Created Armor",
  "description": "Custom armor created by user",
  "price": 1500,
  "hasUsdPrice": true,
  "virtualCurrencyPrices": [
    {
      "currencyId": "cur_123",
      "amount": 100
    }
  ],
  "virtualCurrencyDetails": [
    {
      "_id": "cur_123",
      "code": "GEM",
      "name": "Gems"
    }
  ],
  "imageUrl": "https://cdn.example.com/items/ugc-armor.png",
  "metadata": {
    "rarity": "legendary",
    "idempotencyKey": "ugc-armor-20240501"
  },
  "perUserLimit": 1,
  "isVisible": true,
  "isPriceVisible": true,
  "forSale": true,
  "fulfillmentType": "WEBHOOK",
  "createdAt": "2024-04-22T18:07:43.123Z",
  "updatedAt": "2024-04-22T18:07:43.123Z"
}

List Creator ProductsGET

/v1/products/{userRef}

List products created by a specific user.

curl -X GET https://oncade.gg/api/v1/products/user_123 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Get User BalancePOST

/v1/wallet/balance

Return wallet address and balance for a user. Requires Idempotency-Key.

curl -X POST https://oncade.gg/api/v1/wallet/balance \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 9935cde1-ccba-4b82-927c-f77dc1311c52" \
  -H "Content-Type: application/json" \
  -d '{
  "userId": "user_123"
}'

Example Response

{
  "address": "0xabcDEFabcDEFabcDEFabcDEFabcDEFabcDEFabcd",
  "balance": "1500000"
}

Get Manage Wallet LinkPOST

/v1/wallet/manage

Generate a profile management link for a user. Requires Idempotency-Key.

curl -X POST https://oncade.gg/api/v1/wallet/manage \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 369585f2-5af4-4bdc-aec8-c0d100ded319" \
  -H "Content-Type: application/json" \
  -d '{
  "userId": "user_123"
}'

Example Response

{
  "linkUrl": "https://oncade.gg/dashboard/profile"
}

Get Wallet PurchaseGET

/v1/wallet/purchase/{purchaseId}

Fetch status and payout details for a wallet purchase.

curl -X GET https://oncade.gg/api/v1/wallet/purchase/purchase_abc123 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "data": {
    "_id": "purchase_abc123",
    "itemId": "65fa1234abcdef5678901234",
    "userId": "507f1f77bcf86cd799439011",
    "gameId": "game_123",
    "environment": "test",
    "status": "pending",
    "fulfillmentStatus": "pending",
    "priceInCents": 1000,
    "taxAmountInCents": 0,
    "feeRate": {
      "percentage": 10,
      "flat": 0
    },
    "feeName": "walletFee",
    "payouts": [
      {
        "recipient": "creator",
        "recipientAddress": "0xCreatorAddress",
        "amount": 700
      },
      {
        "recipient": "platform",
        "recipientAddress": "0xPlatformAddress",
        "amount": 300
      }
    ],
    "createdAt": "2024-01-01T00:00:00.000Z",
    "updatedAt": "2024-01-01T00:00:00.000Z"
  }
}

Initiate Virtual Currency PurchasePOST

/v1/vc/purchases

Start a virtual currency purchase. Returns 201 with the amount to debit and a link to the complete endpoint.

curl -X POST https://oncade.gg/api/v1/vc/purchases \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 3a91a329-f885-4a83-917a-0d6a0491ed27" \
  -H "Content-Type: application/json" \
  -d '{
  "userId": "link_usr_123",
  "itemId": "65fa1234abcdef5678901234",
  "currencyId": "cur_abc123",
  "affiliateCode": "STREAMER123",
  "dealCode": "GEMS_SALE",
  "metadata": {
    "campaign": "spring"
  }
}'

Example Response

{
  "data": {
    "purchaseId": "purchase_abc123",
    "currencyId": "cur_abc123",
    "amountUnits": "800"
  }
}

Complete Virtual Currency PurchasePOST

/v1/vc/purchases/{purchaseId}

Complete a virtual currency purchase. Debits the balance and triggers fulfillment. Idempotent via Idempotency-Key.

curl -X POST https://oncade.gg/api/v1/vc/purchases/purchase_abc123 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: b38aa887-e88e-4dde-b826-04d39b23c339"

Example Response

{
  "data": {
    "purchaseId": "purchase_abc123",
    "journalId": "txn_xyz789",
    "newBalanceUnits": "9000",
    "purchase": {
      "_id": "purchase_abc123",
      "status": "completed",
      "isPaid": true,
      "fulfillmentStatus": "completed"
    }
  }
}

Get Checkout ThemeGET

/v1/checkout/theme

Return the checkout theme for a game. Falls back to store theme colors if no game theme is set.

curl -X GET https://oncade.gg/api/v1/checkout/theme?gameId=test-game&itemId=65fa1234abcdef5678901234 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "primaryButtonColor": "#3B82F6",
  "secondaryButtonColor": "#22C55E",
  "notifyButtonColor": "#374151",
  "backgroundColor": "#1F2937",
  "borderColor": "#374151",
  "priceOverrideColor": "#4ade80",
  "logoUrl": "https://cdn.oncade.com/logos/game.png"
}

Get Store Checkout URLGET

/v1/checkout/redirect

Return a storefront checkout URL for an item. Use checkoutMethod to auto-select a payment method. Returns 400 for invalid deal codes, 410 if the item is not for sale.

curl -X GET https://oncade.gg/api/v1/checkout/redirect?gameId=test-game&itemId=65fa1234abcdef5678901234&checkoutmethod=credit \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "status": 200,
  "headers": {
    "Location": "https://oncade.gg/games/test-game/items/65fa1234abcdef5678901234?mode=api&checkoutmethod=credit"
  },
  "body": {
    "url": "https://oncade.gg/games/test-game/items/65fa1234abcdef5678901234?mode=api&checkoutmethod=credit"
  }
}

Create Checkout GrantPOST

/v1/checkout/grants

Create a signed checkout grant so players can purchase without authenticating on Oncade first. Returns a one-time checkout URL (expires after 2 hours). If no userRef is provided, one is generated or looked up by email. The same email always resolves to the same userRef per game.

curl -X POST https://oncade.gg/api/v1/checkout/grants \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: aa8444ca-d9a2-4ace-9e97-0b6ac51adc33" \
  -H "Content-Type: application/json" \
  -d '{
  "itemId": "65fa1234abcdef5678901234",
  "email": "player@example.com",
  "checkoutMetadata": {
    "orderId": "game-order-12345",
    "playerId": "player-abc",
    "source": "in-game-store"
  },
  "customMessage": "Thank you for your purchase! Your items will be delivered within 24 hours."
}'

Example Response

{
  "checkoutUrl": "https://oncade.gg/checkout/grant?checkoutGrantId=550e8400-e29b-41d4-a716-446655440000&sig=abc123...",
  "userRef": "user_abc123def456"
}

List Split TemplatesGET

/v1/split-templates

List non-archived split templates for the business, newest first.

curl -X GET https://oncade.gg/api/v1/split-templates \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "templates": [
    {
      "_id": "64b10b1cec13f995e9000011",
      "name": "Team Revenue Split",
      "description": "Default split for team revenue sharing",
      "businessId": "64b10b1cec13f995e9000012",
      "createdBy": "usr_123",
      "recipients": [
        {
          "email": "dev1@example.com",
          "name": "Developer 1",
          "percentage": 50
        },
        {
          "email": "dev2@example.com",
          "name": "Developer 2",
          "percentage": 30
        },
        {
          "email": "dev3@example.com",
          "name": "Developer 3",
          "percentage": 20
        }
      ],
      "isArchived": false,
      "createdAt": "2024-01-01T00:00:00.000Z",
      "updatedAt": "2024-01-01T00:00:00.000Z"
    }
  ],
  "total": 1
}

Create Split TemplatePOST

/v1/split-templates

Create a split template. Recipient percentages must sum to 100%. Names must be unique per business. Returns 201.

curl -X POST https://oncade.gg/api/v1/split-templates \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 8d7ed318-fe0d-49e0-b8a5-256e182d2f4a" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Team Revenue Split",
  "description": "Default split for team revenue sharing",
  "recipients": "[\n  {\n    \"email\": \"dev1@example.com\",\n    \"name\": \"Developer 1\",\n    \"percentage\": 50\n  },\n  {\n    \"email\": \"dev2@example.com\",\n    \"name\": \"Developer 2\",\n    \"percentage\": 30\n  },\n  {\n    \"email\": \"dev3@example.com\",\n    \"name\": \"Developer 3\",\n    \"percentage\": 20\n  }\n]"
}'

Example Response

{
  "_id": "64b10b1cec13f995e9000011",
  "name": "Team Revenue Split",
  "description": "Default split for team revenue sharing",
  "businessId": "64b10b1cec13f995e9000012",
  "createdBy": "usr_123",
  "recipients": [
    {
      "email": "dev1@example.com",
      "name": "Developer 1",
      "percentage": 50
    },
    {
      "email": "dev2@example.com",
      "name": "Developer 2",
      "percentage": 30
    },
    {
      "email": "dev3@example.com",
      "name": "Developer 3",
      "percentage": 20
    }
  ],
  "isArchived": false,
  "createdAt": "2024-01-01T00:00:00.000Z",
  "updatedAt": "2024-01-01T00:00:00.000Z"
}

Get Split TemplateGET

/v1/split-templates/{templateId}

Fetch a split template by ID.

curl -X GET https://oncade.gg/api/v1/split-templates/64b10b1cec13f995e9000011 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "_id": "64b10b1cec13f995e9000011",
  "name": "Team Revenue Split",
  "description": "Default split for team revenue sharing",
  "businessId": "64b10b1cec13f995e9000012",
  "createdBy": "usr_123",
  "recipients": [
    {
      "email": "dev1@example.com",
      "name": "Developer 1",
      "percentage": 50
    },
    {
      "email": "dev2@example.com",
      "name": "Developer 2",
      "percentage": 30
    },
    {
      "email": "dev3@example.com",
      "name": "Developer 3",
      "percentage": 20
    }
  ],
  "isArchived": false,
  "createdAt": "2024-01-01T00:00:00.000Z",
  "updatedAt": "2024-01-01T00:00:00.000Z"
}

Update Split TemplatePUT

/v1/split-templates/{templateId}

Update a split template. All fields optional. If recipients change, percentages must still sum to 100%.

curl -X PUT https://oncade.gg/api/v1/split-templates/64b10b1cec13f995e9000011 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 9db53032-fddd-40f2-9524-667ac9572e29" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Updated Team Split",
  "recipients": "[\n  {\n    \"email\": \"dev1@example.com\",\n    \"name\": \"Developer 1\",\n    \"percentage\": 60\n  },\n  {\n    \"email\": \"dev2@example.com\",\n    \"name\": \"Developer 2\",\n    \"percentage\": 40\n  }\n]"
}'

Example Response

{
  "_id": "64b10b1cec13f995e9000011",
  "name": "Updated Team Split",
  "description": "Default split for team revenue sharing",
  "businessId": "64b10b1cec13f995e9000012",
  "createdBy": "usr_123",
  "recipients": [
    {
      "email": "dev1@example.com",
      "name": "Developer 1",
      "percentage": 60
    },
    {
      "email": "dev2@example.com",
      "name": "Developer 2",
      "percentage": 40
    }
  ],
  "isArchived": false,
  "createdAt": "2024-01-01T00:00:00.000Z",
  "updatedAt": "2024-01-02T00:00:00.000Z"
}

Get Split Template Redirect URLGET

/v1/split-templates/{templateId}/redirect

Return a redirect URL to the DevPortal distribution page with this template pre-loaded.

curl -X GET https://oncade.gg/api/v1/split-templates/64b10b1cec13f995e9000011/redirect?amount=1000 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "url": "https://dev.oncade.gg/dashboard/business/team-payouts/distribute?templateId=64b10b1cec13f995e9000011&amount=1000"
}

Create Ghost UserPOST

/v1/platform/vc/users

Create a ghost user for virtual currency operations. If an email is provided, the call is idempotent — the same email always resolves to the same user. Returns 409 if the email belongs to an existing authenticated user. Requires platform API key with vc:user:create scope.

curl -X POST https://oncade.gg/api/v1/platform/vc/users \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 8fb6fe9c-9abf-4a91-b145-8deb76dcd0a0" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "player@example.com"
}'

Example Response

{
  "userId": "pvu_a1b2c3d4-e5f6-5a7b-8c9d-0e1f2a3b4c5d"
}

Get User VC Balance (Platform)GET

/v1/platform/vc/balances

Fetch a user's virtual currency balance. Requires platform API key with vc:balance:read scope, X-Target-Business-Id, and X-Game-Id headers.

curl -X GET https://oncade.gg/api/v1/platform/vc/balances?currencyId=cur_123&userId=pvu_a1b2c3d4-e5f6-5a7b-8c9d-0e1f2a3b4c5d \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "currencyId": "cur_123",
  "userId": "pvu_a1b2c3d4-e5f6-5a7b-8c9d-0e1f2a3b4c5d",
  "balanceUnits": "500",
  "updatedAt": "2024-05-01T00:00:00.000Z"
}

Credit VC Balance (Platform)POST

/v1/platform/vc/credits

Credit virtual currency to a user via platform API key. Requires vc:credit scope, X-Target-Business-Id, X-Game-Id, and Idempotency-Key headers.

curl -X POST https://oncade.gg/api/v1/platform/vc/credits \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: fca59446-74c4-49dc-92e5-9298b2c151f7" \
  -H "Content-Type: application/json" \
  -d '{
  "currencyId": "cur_123",
  "userId": "pvu_a1b2c3d4-e5f6-5a7b-8c9d-0e1f2a3b4c5d",
  "amountUnits": "500",
  "orderId": "stripe-order-123"
}'

Example Response

{
  "journalId": "jrnl_002",
  "newBalanceUnits": "1500"
}

Debit VC Balance (Platform)POST

/v1/platform/vc/debits

Debit virtual currency from a user via platform API key. Requires vc:debit scope, X-Target-Business-Id, X-Game-Id, and Idempotency-Key headers.

curl -X POST https://oncade.gg/api/v1/platform/vc/debits \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: c395f3d5-5dd9-43b0-9dcc-af6ff42c767f" \
  -H "Content-Type: application/json" \
  -d '{
  "currencyId": "cur_123",
  "userId": "pvu_a1b2c3d4-e5f6-5a7b-8c9d-0e1f2a3b4c5d",
  "amountUnits": "250",
  "reason": "refund"
}'

Example Response

{
  "journalId": "jrnl_003",
  "newBalanceUnits": "1250"
}

Batch VC Transfer (Platform)POST

/v1/platform/vc/batch

Atomically debit one user and distribute to multiple recipients via platform API key. Requires vc:batch scope, X-Target-Business-Id, X-Game-Id, and Idempotency-Key headers.

curl -X POST https://oncade.gg/api/v1/platform/vc/batch \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: ba33b603-3c21-421f-aeb8-23f0670b15c7" \
  -H "Content-Type: application/json" \
  -d '{
  "currencyId": "cur_123",
  "sourceUserId": "pvu_a1b2c3d4-e5f6-5a7b-8c9d-0e1f2a3b4c5d",
  "recipients": "[\n  {\n    \"userId\": \"pvu_b2c3d4e5-f6a7-5b8c-9d0e-1f2a3b4c5d6e\",\n    \"amountUnits\": \"100\",\n    \"description\": \"Winner payout\"\n  },\n  {\n    \"toPool\": true,\n    \"amountUnits\": \"25\",\n    \"description\": \"Platform fee\"\n  }\n]"
}'

Example Response

{
  "journalId": "jrnl_batch_001",
  "newBalanceUnits": "375"
}

Purchase Item with VC (Platform)POST

/v1/platform/vc/purchases

Purchase an item using virtual currency on behalf of a user. Debits the user's balance and records the purchase. Supports idempotency — replaying the same Idempotency-Key returns the original result. Requires platform API key with vc:purchase scope, X-Target-Business-Id, X-Game-Id, and Idempotency-Key headers.

curl -X POST https://oncade.gg/api/v1/platform/vc/purchases \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 53c9e6ce-45d2-4fef-b70a-2e4f45565c0f" \
  -H "Content-Type: application/json" \
  -d '{
  "itemId": "507f1f77bcf86cd799439011",
  "userId": "pvu_a1b2c3d4-e5f6-5a7b-8c9d-0e1f2a3b4c5d",
  "currencyId": "507f1f77bcf86cd799439022",
  "quantity": 1
}'

Example Response

{
  "purchaseId": "507f1f77bcf86cd799439033",
  "journalId": "jrnl_004",
  "totalAmountUnits": "500",
  "newBalanceUnits": "1500",
  "item": {
    "id": "507f1f77bcf86cd799439011",
    "name": "Gold Sword"
  }
}

List User Purchases (Platform)GET

/v1/platform/vc/users/{userRef}/purchases

List completed virtual currency purchases for a user. Supports pagination and filtering by game, currency, and date range. Requires platform API key with vc:purchase:read scope, X-Target-Business-Id, and X-Game-Id headers.

curl -X GET https://oncade.gg/api/v1/platform/vc/users/pvu_a1b2c3d4-e5f6-5a7b-8c9d-0e1f2a3b4c5d/purchases?page=1&limit=20 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "items": [
    {
      "_id": "507f1f77bcf86cd799439033",
      "platformUserId": "pvu_a1b2c3d4-e5f6-5a7b-8c9d-0e1f2a3b4c5d",
      "gameId": "game_001",
      "itemId": "507f1f77bcf86cd799439011",
      "itemName": "Gold Sword",
      "currencyId": "507f1f77bcf86cd799439022",
      "unitPrice": "500",
      "quantity": 1,
      "totalAmountUnits": "500",
      "journalId": "jrnl_004",
      "status": "completed",
      "createdAt": "2025-01-15T10:00:00.000Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "totalCount": 1,
    "totalPages": 1,
    "hasNextPage": false,
    "hasPrevPage": false
  }
}

List Business Linked Users (Platform)GET

/v1/platform/business/users

List users linked to the target business (paginated), or search them by email/name with ?search=. userRefs are env-prefixed. Requires platform API key with business:users:link:read scope and X-Target-Business-Id header.

curl -X GET https://oncade.gg/api/v1/platform/business/users?page=1&limit=20 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "users": [
    {
      "linkId": "507f1f77bcf86cd799439044",
      "userRef": "obu_test_a1b2c3d4-e5f6-5a7b-8c9d-0e1f2a3b4c5d",
      "email": "player@example.com",
      "name": "Player One",
      "linkedAt": "2026-01-15T10:00:00.000Z",
      "environment": "test"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "totalCount": 1,
    "totalPages": 1,
    "hasNextPage": false,
    "hasPrevPage": false
  }
}

Record Gameplay Event (Platform)POST

/v1/platform/gameplay/events

Record a gameplay event (e.g. gameplay minutes, achievements) for a platform user. Uses idempotency key to prevent duplicate recording. Requires platform API key with gameplay:event:create scope.

curl -X POST https://oncade.gg/api/v1/platform/gameplay/events \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: f45c458f-03bc-40b0-8323-ace51350dc2f" \
  -H "Content-Type: application/json" \
  -d '{
  "userId": "pvu_a1b2c3d4-e5f6-5a7b-8c9d-0e1f2a3b4c5d",
  "gameId": "game_001",
  "eventName": "gameplay_minutes",
  "description": "30 minutes of gameplay"
}'

Example Response

{
  "eventId": "platform-plat_001-idem_key_123",
  "recorded": true
}

Create Item (Platform)POST

/v1/platform/items

Create a new game item in the catalog. The item is created with isVisible=false (platform items are never shown on the public storefront). Supports USD pricing, virtual currency pricing, or both. Requires platform API key with item:create scope, X-Target-Business-Id header, and Idempotency-Key header.

curl -X POST https://oncade.gg/api/v1/platform/items \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 1822451b-5176-4686-80f6-1e4829125289" \
  -H "Content-Type: application/json" \
  -d '{
  "gameId": "game_001",
  "name": "Gold Sword",
  "type": "consumable",
  "fulfillmentType": "GRANT_VIRTUAL_CURRENCY",
  "description": "A powerful golden sword",
  "hasUsdPrice": "false",
  "virtualCurrencyPrices": "[\n  [\n    \"507f1f77bcf86cd799439022\",\n    500\n  ]\n]",
  "grantVirtualCurrencyId": "507f1f77bcf86cd799439022",
  "grantAmount": 100,
  "metadata": {
    "rarity": "legendary"
  },
  "forSale": "true"
}'

Example Response

{
  "_id": "507f1f77bcf86cd799439011",
  "gameId": "game_001",
  "name": "Gold Sword",
  "type": "consumable",
  "description": "A powerful golden sword",
  "hasUsdPrice": false,
  "price": 0,
  "virtualCurrencyPrices": [
    [
      "507f1f77bcf86cd799439022",
      500
    ]
  ],
  "fulfillmentType": "GRANT_VIRTUAL_CURRENCY",
  "forSale": true,
  "isVisible": false,
  "perUserLimit": 0,
  "createdAt": "2025-01-15T10:00:00.000Z",
  "updatedAt": "2025-01-15T10:00:00.000Z"
}

List Items (Platform)GET

/v1/platform/items

List all items for a game with pagination. Returns items sorted by creation date (newest first). Requires platform API key with item:read scope and X-Target-Business-Id header.

curl -X GET https://oncade.gg/api/v1/platform/items?gameId=game_001&page=1&limit=50 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "items": [
    {
      "_id": "507f1f77bcf86cd799439011",
      "gameId": "game_001",
      "name": "Gold Sword",
      "type": "consumable",
      "hasUsdPrice": false,
      "price": 0,
      "virtualCurrencyPrices": [
        [
          "507f1f77bcf86cd799439022",
          500
        ]
      ],
      "fulfillmentType": "GRANT_VIRTUAL_CURRENCY",
      "forSale": true,
      "isVisible": false,
      "createdAt": "2025-01-15T10:00:00.000Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 50,
    "total": 1,
    "totalPages": 1
  }
}

Get Item (Platform)GET

/v1/platform/items/{itemId}

Retrieve a single item by ID. The item must belong to a game owned by the target business. Requires platform API key with item:read scope and X-Target-Business-Id header.

curl -X GET https://oncade.gg/api/v1/platform/items/507f1f77bcf86cd799439011 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "_id": "507f1f77bcf86cd799439011",
  "gameId": "game_001",
  "name": "Gold Sword",
  "type": "consumable",
  "description": "A powerful golden sword",
  "hasUsdPrice": false,
  "price": 0,
  "virtualCurrencyPrices": [
    [
      "507f1f77bcf86cd799439022",
      500
    ]
  ],
  "fulfillmentType": "GRANT_VIRTUAL_CURRENCY",
  "forSale": true,
  "isVisible": false,
  "perUserLimit": 0,
  "createdAt": "2025-01-15T10:00:00.000Z",
  "updatedAt": "2025-01-15T10:00:00.000Z"
}

Update Item (Platform)PATCH

/v1/platform/items/{itemId}

Update an existing item. Only provided fields are modified — omitted fields remain unchanged. The item must belong to a game owned by the target business. Requires platform API key with item:update scope and X-Target-Business-Id header.

curl -X PATCH https://oncade.gg/api/v1/platform/items/ \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -d '{
  "name": "Diamond Sword",
  "virtualCurrencyPrices": "[\n  [\n    \"507f1f77bcf86cd799439022\",\n    750\n  ]\n]",
  "forSale": "true"
}'

Example Response

{
  "_id": "507f1f77bcf86cd799439011",
  "gameId": "game_001",
  "name": "Diamond Sword",
  "type": "consumable",
  "description": "A powerful golden sword",
  "hasUsdPrice": false,
  "price": 0,
  "virtualCurrencyPrices": [
    [
      "507f1f77bcf86cd799439022",
      750
    ]
  ],
  "fulfillmentType": "GRANT_VIRTUAL_CURRENCY",
  "forSale": true,
  "isVisible": false,
  "perUserLimit": 0,
  "createdAt": "2025-01-15T10:00:00.000Z",
  "updatedAt": "2025-01-15T12:00:00.000Z"
}

Archive Item (Platform)DELETE

/v1/platform/items/{itemId}

Archive an item by setting forSale=false and isVisible=false. The item is not permanently deleted. Requires platform API key with item:archive scope and X-Target-Business-Id header.

curl -X DELETE https://oncade.gg/api/v1/platform/items/507f1f77bcf86cd799439011 \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

null

List Gameplay Rollups (Platform)GET

/v1/platform/gameplay/rollup

List gameplay rollups for the platform, optionally filtered by status. If a period query param is provided, returns the single rollup for that period instead of a list. Requires platform API key with gameplay:rollup:read scope.

curl -X GET https://oncade.gg/api/v1/platform/gameplay/rollup?status=draft \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1"

Example Response

{
  "rollups": [
    {
      "_id": "507f1f77bcf86cd799439011",
      "platformId": "plat_001",
      "businessId": "507f1f77bcf86cd799439022",
      "period": "2026-05",
      "status": "draft",
      "totalMinutes": 1200,
      "games": [
        {
          "gameId": "game_001",
          "gameName": "Space Blasters",
          "minutes": 720,
          "share": 0.6,
          "skuId": null,
          "skuDisplayName": null
        },
        {
          "gameId": "game_002",
          "gameName": "Puzzle Quest",
          "minutes": 480,
          "share": 0.4,
          "skuId": null,
          "skuDisplayName": null
        }
      ],
      "createdAt": "2026-06-01T00:00:00.000Z",
      "updatedAt": "2026-06-01T00:00:00.000Z"
    }
  ],
  "total": 1
}

Generate Gameplay Rollup (Platform)POST

/v1/platform/gameplay/rollup

Generate a gameplay rollup for a given period. Aggregates all gameplay_minutes events for the platform during that month into a per-game breakdown. If a draft rollup already exists for the period it is overwritten; if a confirmed rollup exists the request is rejected. Requires platform API key with gameplay:rollup:generate scope.

curl -X POST https://oncade.gg/api/v1/platform/gameplay/rollup \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 07518b37-cb9c-43a0-beee-a888722e3cf2" \
  -H "Content-Type: application/json" \
  -d '{
  "period": "2026-05"
}'

Example Response

{
  "rollup": {
    "_id": "507f1f77bcf86cd799439011",
    "platformId": "plat_001",
    "businessId": "507f1f77bcf86cd799439022",
    "period": "2026-05",
    "status": "draft",
    "totalMinutes": 1200,
    "games": [
      {
        "gameId": "game_001",
        "gameName": "Space Blasters",
        "minutes": 720,
        "share": 0.6,
        "skuId": null,
        "skuDisplayName": null
      },
      {
        "gameId": "game_002",
        "gameName": "Puzzle Quest",
        "minutes": 480,
        "share": 0.4,
        "skuId": null,
        "skuDisplayName": null
      }
    ],
    "createdAt": "2026-06-01T00:00:00.000Z",
    "updatedAt": "2026-06-01T00:00:00.000Z"
  }
}

Confirm Gameplay Rollup (Platform)POST

/v1/platform/gameplay/rollup/confirm

Confirm a draft gameplay rollup for a given period. Once confirmed, the rollup cannot be regenerated. This endpoint only changes the rollup status — to create a distribution from the confirmed rollup, use the Pay dashboard. Requires platform API key with gameplay:rollup:confirm scope.

curl -X POST https://oncade.gg/api/v1/platform/gameplay/rollup/confirm \
  -H "Authorization: Bearer SERVER_API_KEY" \
  -H "X-Game-Id: GAME_ID" \
  -H "X-Oncade-API-Version: v1" \
  -H "Idempotency-Key: 4ad6e761-a76e-43d1-9595-0c695c1dddad" \
  -H "Content-Type: application/json" \
  -d '{
  "period": "2026-05"
}'

Example Response

{
  "rollup": {
    "_id": "507f1f77bcf86cd799439011",
    "platformId": "plat_001",
    "businessId": "507f1f77bcf86cd799439022",
    "period": "2026-05",
    "status": "confirmed",
    "totalMinutes": 1200,
    "games": [
      {
        "gameId": "game_001",
        "gameName": "Space Blasters",
        "minutes": 720,
        "share": 0.6,
        "skuId": "sku_001",
        "skuDisplayName": "Space Blasters"
      },
      {
        "gameId": "game_002",
        "gameName": "Puzzle Quest",
        "minutes": 480,
        "share": 0.4,
        "skuId": "sku_002",
        "skuDisplayName": "Puzzle Quest"
      }
    ],
    "confirmedAt": "2026-06-02T12:00:00.000Z",
    "confirmedBy": "key_abc123",
    "createdAt": "2026-06-01T00:00:00.000Z",
    "updatedAt": "2026-06-02T12:00:00.000Z"
  }
}