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.

i

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.

Loading diagram…
  1. Your server creates a grant — Call POST /v1/checkout/grants with the item ID and optional parameters (email, metadata, custom message). A stable userRef is returned whether the email is new or belongs to an existing account.
  2. Redirect the consumer — The response includes a checkoutUrl. Send the consumer to this URL (redirect, link, QR code, etc.).
  3. Consumer completes checkout — They enter an email (if not pre-filled), choose a payment method, and pay. No account is required for eligible items.
  4. Your server receives a webhook — The Purchases.Completed webhook includes grant_user_ref and any checkout_metadata you 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.

Loading diagram…
StateMeaning
pendingGrant created, waiting for consumer to open the checkout URL
claimedConsumer has started checkout (can change payment methods)
completedPayment succeeded — grant permanently consumed
expiredGrant was not used within 2 hours of creation
i

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/grants

The response returns:

FieldDescription
checkoutUrlFull URL to redirect the consumer to for checkout
userRefStable 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/grants
i

Stable 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
ParameterDescriptionLimits
checkoutMetadataJSON object echoed back in webhooks for server-side correlationMax 10KB, 2 levels deep, 50 keys per level
customMessagePlain text displayed above the checkout card to the consumerMax 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/grants
!

Validation: 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.

Loading diagram…

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.

Loading diagram…
i

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.

i

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.

Loading diagram…

Webhook payload

Grant-based purchases include additional fields in the webhook payload for correlation:

FieldDescription
user_refThe 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_refThe userRef returned when the grant was created. Useful for matching the webhook back to the original grant issuance.
checkout_metadataThe 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.

Loading diagram…

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.

EventTrigger
Purchases.StartedConsumer started checkout (payment session created)
Purchases.CompletedPayment succeeded, fulfillment processed
Purchases.CanceledConsumer cancelled the checkout
Purchases.FailedPayment 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.

StatusCodeMeaning
201Grant created successfully
400INVALID_USER_REFProvided userRef does not exist for this game
400METADATA_INVALIDMetadata exceeds size/depth limits
400CUSTOM_MESSAGE_INVALIDCustom message is not a string or exceeds 256 characters. HTML tags are stripped automatically.
403Item belongs to a different game than the server key
404Item not found
410Item is not visible or not for sale

API Quick Reference

MethodPathAuthPurpose
POST/v1/checkout/grantsServer API KeyCreate a checkout grant and receive a checkout URL

Request body

FieldTypeRequiredDescription
itemIdstringYesThe store item to create the checkout for
emailstringNoPre-fill the consumer's email for receipt delivery
userRefstringNoExisting user reference from account linking
checkoutMetadataobjectNoServer-side metadata echoed in webhooks (max 10KB)
customMessagestringNoMessage shown above the checkout card (max 256 chars)

Required headers

HeaderValue
AuthorizationBearer <server_api_key>
X-Game-IdYour game ID
X-Oncade-API-Versionv1
Content-Typeapplication/json

Best Practices

  • Always include an email when you know the consumer's email. This pre-fills the checkout form and reduces abandonment.
  • Use checkoutMetadata for correlation rather than parsing the userRef. 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 userRef on 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.Completed events. This is the reliable way to know a purchase succeeded, rather than relying on redirect callbacks.

References