Grant-Based Checkout Guide
Grant-based checkout lets your server initiate a purchase on behalf of a consumer. Your server creates a checkout grant for a specific item and receives a URL. The consumer opens that URL, completes payment, and your server is notified via webhook.
This is ideal when you want to control what a user can buy from your own application while letting Oncade handle the checkout experience and payment processing.
Key benefit: Consumers can complete purchases as guests — no account creation required. They just provide an email for the receipt and pay.
How It Works
The grant checkout flow has three participants: your server, the Oncade API, and the consumer.
- Your server creates a grant — Call
POST /v1/checkout/grantswith the item ID and optional parameters (email, metadata, custom message). A stableuserRefis returned whether the email is new or belongs to an existing account. - Redirect the consumer — The response includes a
checkoutUrl. Send the consumer to this URL (redirect, link, QR code, etc.). - Consumer completes checkout — They enter an email (if not pre-filled), choose a payment method, and pay. No account is required for eligible items.
- Your server receives a webhook — The
Purchases.Completedwebhook includesgrant_user_refand anycheckout_metadatayou attached, so you can correlate the purchase back to your system.
Grant Lifecycle
Each grant moves through a defined set of states. Understanding the lifecycle helps you handle edge cases like cancellations and retries.
| State | Meaning |
|---|---|
pending | Grant created, waiting for consumer to open the checkout URL |
claimed | Consumer has started checkout (can change payment methods) |
completed | Payment succeeded — grant permanently consumed |
expired | Grant was not used within 2 hours of creation |
Retry-safe: If a consumer cancels their payment without completing, the grant returns to pending and they can re-open the same checkout URL to try again (as long as it hasn't expired).
Step 1: Create a Checkout Grant
Your server calls POST /v1/checkout/grants to create a grant. Authentication uses your Server API Key (Bearer token) with the X-Game-Id and X-Oncade-API-Version: v1 headers.
Basic grant (anonymous)
The simplest form creates a grant with no pre-filled email. The consumer provides their email during checkout.
curl -s -X POST \
-H "Authorization: Bearer $SERVER_API_KEY" \
-H "X-Game-Id: $GAME_ID" \
-H "X-Oncade-API-Version: v1" \
-H "Content-Type: application/json" \
-d '{"itemId":"<item_id>"}' \
https://<host>/api/v1/checkout/grantsThe response returns:
| Field | Description |
|---|---|
checkoutUrl | Full URL to redirect the consumer to for checkout |
userRef | Stable user reference for correlating webhooks back to this grant |
Grant with email (recommended)
When you know the consumer's email, include it in the grant. The email is pre-filled in the checkout form, reducing friction.
curl -s -X POST \
-H "Authorization: Bearer $SERVER_API_KEY" \
-H "X-Game-Id: $GAME_ID" \
-H "X-Oncade-API-Version: v1" \
-H "Content-Type: application/json" \
-d '{
"itemId": "<item_id>",
"email": "buyer@example.com"
}' \
https://<host>/api/v1/checkout/grantsStable user references: The userRef returned is stable for a given email and game. If the email belongs to an existing account, the grant is associated with that account. If the email is new, a guest account is created. Either way, the same email always resolves to the same userRef for your game.
Note: If the consumer already has an account linked to your game (e.g. via account linking), the webhook user_ref may differ from the grant_user_ref returned at grant creation. The webhook user_ref reflects the account the consumer actually used to complete checkout and should be preferred for subsequent API calls, but the two are not required to match.
Grant with metadata and custom message
Attach server-side metadata to the grant for correlation. The metadata is echoed back in the Purchases.Completed webhook, making it easy to match purchases to your internal records. A custom message can also be displayed to the consumer above the checkout form.
curl -s -X POST \
-H "Authorization: Bearer $SERVER_API_KEY" \
-H "X-Game-Id: $GAME_ID" \
-H "X-Oncade-API-Version: v1" \
-H "Content-Type: application/json" \
-d '{
"itemId": "<item_id>",
"email": "buyer@example.com",
"checkoutMetadata": {
"orderId": "ORD-12345",
"source": "in-game-shop"
},
"customMessage": "Thanks for your purchase!"
}' \
https://<host>/api/v1/checkout/grants| Parameter | Description | Limits |
|---|---|---|
checkoutMetadata | JSON object echoed back in webhooks for server-side correlation | Max 10KB, 2 levels deep, 50 keys per level |
customMessage | Plain text displayed above the checkout card to the consumer | Max 256 characters, plain text only |
Grant with existing user reference
If the consumer already has a userRef from a prior interaction (e.g., account linking), you can pass it to associate the grant with that user.
curl -s -X POST \
-H "Authorization: Bearer $SERVER_API_KEY" \
-H "X-Game-Id: $GAME_ID" \
-H "X-Oncade-API-Version: v1" \
-H "Content-Type: application/json" \
-d '{
"itemId": "<item_id>",
"userRef": "tuid_abc123"
}' \
https://<host>/api/v1/checkout/grantsValidation: If you provide a userRef, it must be a valid reference that already exists for your game. The API returns 400 if the reference is not found.
Step 2: Consumer Checkout Experience
Once the consumer opens the checkoutUrl, they land on the Oncade checkout page for the specified item. The checkout supports two modes: guest checkout and authenticated checkout.
Guest checkout (no account required)
For eligible items, consumers can complete a purchase without creating an account. They only need to provide an email address (for receipt delivery) and a payment method.
If the grant was created with an email, it is pre-filled in the checkout form. The consumer can still change it before paying.
Authenticated checkout
Consumers can optionally sign in during checkout. If they authenticate, their guest account is automatically linked to their real account, giving them access to purchase history and fulfillment details.
Same userRef: Whether the consumer checks out as a guest or signs in, the grant_user_ref in your webhook remains the same. You always get consistent correlation regardless of how the consumer authenticates.
Item eligibility
Grant-based checkout supports all item types that are marked for sale, including key delivery, webhook fulfillment, and other fulfillment types. The consumer can complete the purchase as a guest or choose to sign in.
Note: Direct guest checkout (without a grant) has additional item-type restrictions (e.g. subscriptions and virtual currency grants require an account). Grant checkout bypasses these restrictions because the grant itself establishes the user context needed for fulfillment.
Step 3: Fulfillment & Webhooks
After a successful payment, Oncade processes fulfillment according to the item's configuration (key delivery, webhook notification, etc.) and sends a Purchases.Completed webhook to your server.
Webhook payload
Grant-based purchases include additional fields in the webhook payload for correlation:
| Field | Description |
|---|---|
user_ref | The user reference for the account that completed checkout. Prefer this for subsequent API calls. May differ from grant_user_ref if the consumer signed in with a linked account. |
grant_user_ref | The userRef returned when the grant was created. Useful for matching the webhook back to the original grant issuance. |
checkout_metadata | The checkoutMetadata you attached during grant creation, echoed back exactly. |
Example webhook payload
{
"event": "Purchases.Completed",
"data": {
"purchaseId": "abc123",
"itemId": "<item_id>",
"gameId": "<game_id>",
"amount": 999,
"currency": "USD",
"user_ref": "user_def456ghi789",
"grant_user_ref": "user_abc123def456",
"checkout_metadata": {
"orderId": "ORD-12345",
"source": "in-game-shop"
}
}
}Metadata correlation flow
The checkoutMetadata field is designed for server-to-server correlation. Attach any data your system needs to reconcile the purchase (order IDs, session IDs, user IDs from your system, etc.), and it is returned verbatim in the webhook.
Purchase Webhooks
Grant-based checkouts emit the same purchase lifecycle webhooks as any other checkout. All webhook payloads include grant_user_ref and checkout_metadata when the purchase originated from a grant.
| Event | Trigger |
|---|---|
Purchases.Started | Consumer started checkout (payment session created) |
Purchases.Completed | Payment succeeded, fulfillment processed |
Purchases.Canceled | Consumer cancelled the checkout |
Purchases.Failed | Payment failed (insufficient funds, card declined, etc.) |
See the Webhooks Guide for full payload details and signature verification.
Error Handling
The grant creation endpoint returns structured error responses. Handle these in your server to provide appropriate feedback.
| Status | Code | Meaning |
|---|---|---|
201 | — | Grant created successfully |
400 | INVALID_USER_REF | Provided userRef does not exist for this game |
400 | METADATA_INVALID | Metadata exceeds size/depth limits |
400 | CUSTOM_MESSAGE_INVALID | Custom message is not a string or exceeds 256 characters. HTML tags are stripped automatically. |
403 | — | Item belongs to a different game than the server key |
404 | — | Item not found |
410 | — | Item is not visible or not for sale |
API Quick Reference
| Method | Path | Auth | Purpose |
|---|---|---|---|
POST | /v1/checkout/grants | Server API Key | Create a checkout grant and receive a checkout URL |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
itemId | string | Yes | The store item to create the checkout for |
email | string | No | Pre-fill the consumer's email for receipt delivery |
userRef | string | No | Existing user reference from account linking |
checkoutMetadata | object | No | Server-side metadata echoed in webhooks (max 10KB) |
customMessage | string | No | Message shown above the checkout card (max 256 chars) |
Required headers
| Header | Value |
|---|---|
Authorization | Bearer <server_api_key> |
X-Game-Id | Your game ID |
X-Oncade-API-Version | v1 |
Content-Type | application/json |
Best Practices
- Always include an email when you know the consumer's email. This pre-fills the checkout form and reduces abandonment.
- Use
checkoutMetadatafor correlation rather than parsing theuserRef. Metadata is designed for your internal identifiers and is echoed back verbatim in webhooks. - Handle the 2-hour expiration by creating grants close to when the consumer is ready to purchase. If a grant expires, create a new one.
- Store the
userRefon your side when the grant is created. This is your stable reference for matching webhook events to your users. - Set up webhooks to receive
Purchases.Completedevents. This is the reliable way to know a purchase succeeded, rather than relying on redirect callbacks.