IAP API
Introduction
Unity IAP is a unified solution for managing digital commerce and implementing in-app purchases across games, stores, and third-party payment providers. These APIs provide a fully managed entitlement system that handles orders and fulfillment through third-party payment providers.
Concepts
Payment Providers
- Order: A purchase initiated through a third-party payment provider, managed through the entitlement system from creation to fulfillment.
- Entitlement: A player's right to access a purchased product, tracked and managed across all supported payment providers.
Download OpenAPI specification:
Create an order
Initiates an order for a player to purchase a specific product from a payment provider.
Supports webview-based flows and will support other flows in the future (which could return additional
order data). The player information is stored and used to personalize the order experience.
Currently supports exactly one SKU in the request.
Authorizations
Client
HTTP: Client
HTTP Authorization Scheme: bearer
Request body for "{title}"
Media Type:
application/jsonArray of catalog listing identifiers to purchase. Currently must contain exactly one identifier. Replaces because SKUs are not guaranteed to be unique. Each identifier is the Live Content config path of the catalog listing and typically looks like a relative file path. Provide either or .
skusskuscatalogListingIdsCountry of purchase in ISO 3166-1 alpha-2 format. Used by payment providers that require a country-of-purchase signal (currently Codapay only); ignored by others. When omitted, the country is derived from the player's locale as a temporary backward-compatibility fallback for older SDK versions.
Optional. One of or . How the checkout is presented. (default) returns a provider-hosted checkout page in . returns an object (client secret, plus a publishable key for Stripe) for rendering an in-page form via the payment provider's JS SDK and leaves empty. Only supports ; other providers reject the request. In mode the player is never redirected, so only payment methods that don't require a redirect are offered (cards, Apple Pay, Google Pay, Link).
hostedembeddedhostedurlembeddedembeddedInfourlstripeembeddedembeddedOptional. The player-journey channel the order started from, independent of the referer-derived purchase origin. One of or : means the session began at the in-game Purchase UI (i.e. a deep-linked webshop session); means an organic browser first webshop visit. Client-asserted and analytics-grade (same trust level as the map). Honored only for orders arriving with a webshop referer; ignored for in-app/SDK orders (which are always treated as ) and silently dropped when unrecognized. When omitted, the channel is left unspecified.
game_deeplinkdirectgame_deeplinkdirectplayer.identitygame_deeplinkOptional external-link transaction tokens, used by developers to self-report the transaction to Apple/Google. Stored with the order and surfaced in order webhooks; not returned in the order response. Up to two tokens may be supplied because a single Apple external purchase can yield two distinct token types depending on the region — for example an token and a token.
acquisitionlinkOutOptional, internal. The opaque, backend-minted key from a prior link-out session registration (see registerLinkOutSession). Relayed verbatim by the webshop on a game-deeplinked order; the backend exchanges it for the registered device context. Ignored when absent, unrecognised, or when the session's owner does not match the ordering player.
Optional. Arbitrary key/value metadata stored with the order and returned in the order response and order webhooks. Limited to 20 keys; each key is limited to 40 bytes and each value to 100 bytes. Limits are enforced on the UTF-8 byte length, not the character count, so multi-byte characters count multiple times. Orders exceeding these limits are rejected.
Code samples for "{title}":
Request example
curl -X POST \ -H "Authorization: Bearer <YOUR_TOKEN>" \ -H "Content-Type: application/json" \ -d '{ "player": { "playerId": "string", "displayName": "string", "locale": "en-US", "identity": { "unity.installation_id": "abc123", "session.id": "xyz789" } }, "skus": [ "product-sku-123" ], "catalogListingIds": [ "endgame/gems-100.ucat" ], "currency": "USD", "country": "US", "paymentProvider": "stripe", "uiMode": "embedded", "entryChannel": "game_deeplink", "externalTransactionTokens": [ { "store": "apple", "token": "string", "type": "acquisition" } ], "redirectUrls": { "successUrl": "https://shop.unity.com/studio/game?status=success", "cancelUrl": "https://shop.unity.com/studio/game?status=cancelled" }, "customReferenceId": "string", "linkOutSessionId": "string", "metadata": {}, "deviceInfo": { "language": "en-US", "platform": "ios", "localeList": [ "en-US", "es-US" ], "deviceModel": "iPhone13,3", "systemBootTime": 1778138688, "osVersion": "17.0", "appBundleId": "com.example.game", "totalSpace": 256000000000 }}' \ "https://iap.services.api.unity.com/v1/projects/{projectId}/environments/{environmentId}/order"
Response example
{ "id": "string", "projectId": "string", "environmentId": "string", "playerId": "string", "paymentProvider": "stripe", "paymentProviderResourceId": "string", "url": "https://example-webshop.com/products/sku123?session=...", "uiMode": "hosted", "embeddedInfo": { "clientSecret": "cs_test_..._secret", "publishableKey": "pk_test_..." }, "lineItems": [ { "sku": "product-123", "catalogListingId": "endgame/gems-100.ucat", "productType": "consumable" } ], "status": "string", "fulfilledAt": "2020-04-01T13:07:23Z", "revokedAt": "2020-04-01T13:07:23Z", "customReferenceId": "string", "metadata": {}, "createdAt": "2020-04-01T13:07:23Z", "updatedAt": "2020-04-01T13:07:23Z"}
Register link-out device context
Registers the in-game IAP SDK's device-context bundle (device identifiers and
device info) before a webshop link-out and returns a backend-minted
linkOutSessionId. These identifiers are PII and must not travel on the link URL:
the webshop carries only the opaque key and order-create resolves it server-side.
The bundle is bound to the authenticated player and retained with a short TTL.
Authorizations
Client
HTTP: Client
HTTP Authorization Scheme: bearer
Code samples for "{title}":
Request example
curl -X POST \ -H "Authorization: Bearer <YOUR_TOKEN>" \ -H "Content-Type: application/json" \ -d '{ "identity": { "unity.installation_id": "abc123", "session.id": "xyz789" }, "deviceInfo": { "language": "en-US", "platform": "ios", "localeList": [ "en-US", "es-US" ], "deviceModel": "iPhone13,3", "systemBootTime": 1778138688, "osVersion": "17.0", "appBundleId": "com.example.game", "totalSpace": 256000000000 }}' \ "https://iap.services.api.unity.com/v1/projects/{projectId}/environments/{environmentId}/link-out-session"
Response example
{ "linkOutSessionId": "7f3d8c2a-1b4e-4c6a-9d2f-7a1b2c3d4e5f"}
List eligible configured payment providers
Returns the list of configured payment providers the calling player is eligible for, based on their Live Releases
variant tags and the project's tag-to-provider routing configuration. Providers are listed in priority
order, highest first; clients should use the first entry by default. An empty list means no provider is
eligible for this player; clients should handle this as a normal "external payment unavailable" state.
Authorizations
Client
HTTP: Client
HTTP Authorization Scheme: bearer
List player entitlements
Returns an array of all orders that the player is entitled to.
Important: Revoked orders are never included in the response, regardless of product type.
Entitlement logic by product type:
- Consumables: Included if not yet fulfilled.
- Non-consumables: Always included.
- Subscriptions: Not yet supported for external payment providers. Future behavior will be similar to non-consumables but will also require the subscription to not be expired.
If there is a mix of types in the order, the order will be returned if any of the types are entitled.
Authorizations
Client
HTTP: Client
HTTP Authorization Scheme: bearer
Code samples for "{title}":
Request example
curl -X GET \ -H "Authorization: Bearer <YOUR_TOKEN>" \ "https://iap.services.api.unity.com/v1/projects/{projectId}/environments/{environmentId}/orders/entitled"
Response example
[ { "id": "string", "projectId": "string", "environmentId": "string", "playerId": "string", "paymentProvider": "stripe", "paymentProviderResourceId": "string", "url": "https://example-webshop.com/products/sku123?session=...", "uiMode": "hosted", "embeddedInfo": { "clientSecret": "cs_test_..._secret", "publishableKey": "pk_test_..." }, "lineItems": [ { "sku": "product-123", "catalogListingId": "endgame/gems-100.ucat", "productType": "consumable" } ], "status": "string", "fulfilledAt": "2020-04-01T13:07:23Z", "revokedAt": "2020-04-01T13:07:23Z", "customReferenceId": "string", "metadata": {}, "createdAt": "2020-04-01T13:07:23Z", "updatedAt": "2020-04-01T13:07:23Z" }]
Get order status
Retrieves the status of an order. Returns 404 if no information has been received from the payment provider about the purchase yet.
Authorizations
Client
HTTP: Client
HTTP Authorization Scheme: bearer
Code samples for "{title}":
Request example
curl -X GET \ -H "Authorization: Bearer <YOUR_TOKEN>" \ "https://iap.services.api.unity.com/v1/projects/{projectId}/environments/{environmentId}/orders/{orderId}"
Response example
{ "id": "string", "projectId": "string", "environmentId": "string", "playerId": "string", "paymentProvider": "stripe", "paymentProviderResourceId": "string", "url": "https://example-webshop.com/products/sku123?session=...", "uiMode": "hosted", "embeddedInfo": { "clientSecret": "cs_test_..._secret", "publishableKey": "pk_test_..." }, "lineItems": [ { "sku": "product-123", "catalogListingId": "endgame/gems-100.ucat", "productType": "consumable" } ], "status": "string", "fulfilledAt": "2020-04-01T13:07:23Z", "revokedAt": "2020-04-01T13:07:23Z", "customReferenceId": "string", "metadata": {}, "createdAt": "2020-04-01T13:07:23Z", "updatedAt": "2020-04-01T13:07:23Z"}
Update an order
Updates an order. Used to mark an order as fulfilled, cancelled, or revoked.
Authorizations
Client
HTTP: Client
HTTP Authorization Scheme: bearer
Request body for "{title}"
Media Type:
application/jsonUpdates the order status. Supported values are , , and . Only orders with status can be marked as . Only orders with status can be marked as . Orders with or status can be marked as . Once cancelled or revoked, an order cannot be changed to another status.
fulfilledcancelledrevokedcreatedcancelledpaidfulfilledpaidfulfilledrevokedCode samples for "{title}":
Request example
curl -X PATCH \ -H "Authorization: Bearer <YOUR_TOKEN>" \ -H "Content-Type: application/json" \ -d '{ "status": "fulfilled"}' \ "https://iap.services.api.unity.com/v1/projects/{projectId}/environments/{environmentId}/orders/{orderId}"
Response example
{ "id": "string", "projectId": "string", "environmentId": "string", "playerId": "string", "paymentProvider": "stripe", "paymentProviderResourceId": "string", "url": "https://example-webshop.com/products/sku123?session=...", "uiMode": "hosted", "embeddedInfo": { "clientSecret": "cs_test_..._secret", "publishableKey": "pk_test_..." }, "lineItems": [ { "sku": "product-123", "catalogListingId": "endgame/gems-100.ucat", "productType": "consumable" } ], "status": "string", "fulfilledAt": "2020-04-01T13:07:23Z", "revokedAt": "2020-04-01T13:07:23Z", "customReferenceId": "string", "metadata": {}, "createdAt": "2020-04-01T13:07:23Z", "updatedAt": "2020-04-01T13:07:23Z"}
Resolve store-specific product ids to their Unity SKUs
Reverse-lookup endpoint that resolves store-specific product ids
(Apple/Google/etc.) back to their Unity SKU and product type for the
caller's live release. Returned as a map keyed by store, then by
store-specific id; unmatched ids are omitted. When no storeOverrideId is
supplied, every store-specific id for the requested store is returned.
A single store-specific id is expected to map to exactly one Unity SKU
across the catalog. If multiple Unity SKUs (or multiple variants of the
same Unity SKU with different types) declare the same store-specific id
on the same store, only the first match is returned; later collisions
are skipped and logged server-side. Keep store-specific ids unique
across your catalog to avoid this.
Authorizations
Client
HTTP: Client
HTTP Authorization Scheme: bearer
Code samples for "{title}":
Request example
curl -X GET \ -H "Authorization: Bearer <YOUR_TOKEN>" \ "https://iap.services.api.unity.com/v1/projects/{projectId}/catalog/store-overrides"
Response example
{ "google": { "30_GEMS_GOOGLE": { "uSku": "gems_30", "type": "Consumable" } }, "apple": { "30_GEMS_APPLE": { "uSku": "gems_30", "type": "Consumable" } }, "xbox": { "30_GEMS_XBOX": { "uSku": "gems_30", "type": "Consumable" } }, "applemacos": { "30_GEMS_MACOS": { "uSku": "gems_30", "type": "Consumable" } }}