Skip to documentation
Open dashboard
Docs/Server integrations

Runtime and admin API reference

Every operation, parameter, request model, response, and authentication boundary.

Download this chapter
On this page

This reference is generated from the reviewed OpenAPI contract. It covers all 37 runtime, store-ingress, webhook, health, and root-admin operations and their models. Download the OpenAPI YAML for the exact machine-readable contract, including nested/conditional schema constraints.

Choose the correct API boundary

The staging API origin is https://api-staging.cherrysub.com. Operator/local deployments use their own origin. Send JSON with the documented content type. The hosted dashboard's cookie-based /auth and /dashboard interface is a separate hosted API.

  • Public client runtime: iap_pk_ plus X-IAP-Customer-Token for the exact app/customer.
  • Trusted app server: iap_sk_, including token minting and app-scoped catalog/webhook management.
  • Root administration: an operator bearer key from ADMIN_API_KEYS; it is not a project-member credential.
  • Store ingress: verified Apple signed data or authenticated Google Pub/Sub push, not an app bearer key pasted into a notification URL.

Root app creation returns the core app and its first secret key. The hosted project/app creation flow has a different response and project association; use the dashboard/CLI when creating an app in a hosted project.

Runtime error responses use an error field. Keep client-facing event_id values as decimal strings. Subscriber 404 can mean no app-user alias exists yet; current product-set null is an explicit successful empty configuration.

Operation index

MethodPathOperation
GET/livezgetLiveness
GET/readyzgetReadiness
GET/healthzgetHealth
GET/metricsgetMetrics
POST/ingest/apple/assningestAppleNotification
POST/ingest/google/rtdningestGoogleNotification
POST/v1/receiptssubmitReceipt
GET/v1/subscribers/{app_user_id}getSubscriber
GET/v1/product-sets/currentgetCurrentProductSet
GET/v1/webhook-endpointslistWebhookEndpoints
POST/v1/webhook-endpointscreateWebhookEndpoint
GET/v1/webhook-endpoints/{endpoint_id}getWebhookEndpoint
PATCH/v1/webhook-endpoints/{endpoint_id}updateWebhookEndpoint
DELETE/v1/webhook-endpoints/{endpoint_id}deleteWebhookEndpoint
POST/v1/webhook-endpoints/{endpoint_id}/rotate-secretrotateWebhookEndpointSecret
GET/v1/webhook-deliverieslistWebhookDeliveries
GET/v1/webhook-deliveries/{message_id}getWebhookDelivery
POST/v1/webhook-deliveries/{message_id}/retryretryWebhookDelivery
GET/admin/v1/appslistApps
POST/admin/v1/appscreateApp
GET/admin/v1/apps/{app_id}getApp
PATCH/admin/v1/apps/{app_id}updateApp
DELETE/admin/v1/apps/{app_id}disableApp
GET/admin/v1/apps/{app_id}/api-keyslistAppAPIKeys
POST/admin/v1/apps/{app_id}/api-keyscreateAppAPIKey
DELETE/admin/v1/apps/{app_id}/api-keys/{key_id}revokeAppAPIKey
GET/v1/access-levelslistAccessLevels
POST/v1/access-levelscreateAccessLevel
GET/v1/access-levels/{access_level_id}getAccessLevel
PATCH/v1/access-levels/{access_level_id}updateAccessLevel
DELETE/v1/access-levels/{access_level_id}archiveAccessLevel
GET/v1/product-access-mappingslistProductAccessMappings
POST/v1/product-access-mappingscreateProductAccessMapping
PATCH/v1/product-access-mappings/{mapping_id}updateProductAccessMapping
DELETE/v1/product-access-mappings/{mapping_id}deleteProductAccessMapping
POST/v1/client-tokenscreateClientToken
DELETE/v1/client-tokens/{token_id}revokeClientToken

Public runtime and trusted catalog

POST /v1/receipts

Operation: submitReceipt. A secret server key may submit directly. A publishable client key must also present X-IAP-Customer-Token and app_user_id must match its authenticated subject. The service then verifies an Apple StoreKit transaction JWS or authoritatively fetches a Google purchase token and atomically reduces mapped access levels.

Authentication: bearerAPIKey

ParameterLocationRequiredTypeDetails
X-IAP-Customer-TokenheaderNostringRequired with an iap_pk_ publishable key; ignored for an iap_sk_ server key. pattern: "^iap_ct_".

Request body: required.

Content type: application/json. ReceiptSubmission

ResponseMeaning
200Receipt observation appended or deduplicated.
400Payload is malformed or fails store validation.
401The required bearer credential is missing, invalid, or revoked.
403The authenticated key or customer token is not authorized for this resource.
413Request exceeds 256 KiB.
422Payload is malformed or fails store validation.
429The authenticated API key exceeded its process-local receipt rate limit.
503A verifier or durable dependency is temporarily unavailable.

200 application/json body: IngestResult

GET /v1/subscribers/{app_user_id}

Operation: getSubscriber. Returns the current Apple and Google access level union for one app-scoped customer alias.

Authentication: bearerAPIKey

ParameterLocationRequiredTypeDetails
app_user_idpathYesstringminLength: 1. maxLength: 512.
X-IAP-Customer-TokenheaderNostringRequired with an iap_pk_ publishable key; ignored for an iap_sk_ server key. pattern: "^iap_ct_".
ResponseMeaning
200Current subscriber access level projection.
400Payload is malformed or fails store validation.
401The required bearer credential is missing, invalid, or revoked.
403The authenticated key or customer token is not authorized for this resource.
404No customer alias exists for this app-user id.
503A verifier or durable dependency is temporarily unavailable.

200 application/json body: Subscriber

GET /v1/product-sets/current

Operation: getCurrentProductSet. Returns the authenticated app's current cross-store product presentation. Publishable keys also require a customer token; secret keys do not.

Authentication: bearerAPIKey

ParameterLocationRequiredTypeDetails
X-IAP-Customer-TokenheaderNostringRequired with an iap_pk_ publishable key; ignored for an iap_sk_ server key. pattern: "^iap_ct_".
ResponseMeaning
200Current product set, or an explicit null when the app has not selected one.
401The required bearer credential is missing, invalid, or revoked.
403The authenticated key or customer token is not authorized for this resource.
503A verifier or durable dependency is temporarily unavailable.

200 application/json body: CurrentProductSet

Response headers: Cache-Control (const: "no-store".).

GET /v1/access-levels

Operation: listAccessLevels.

Authentication: bearerAPIKey

ResponseMeaning
200Active app-scoped access level catalog.
401The required bearer credential is missing, invalid, or revoked.
503A verifier or durable dependency is temporarily unavailable.

200 application/json body:

json
{
  "type": "object",
  "required": [
    "access_levels"
  ],
  "properties": {
    "access_levels": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/CatalogAccessLevel"
      }
    }
  },
  "additionalProperties": false
}

POST /v1/access-levels

Operation: createAccessLevel.

Authentication: bearerAPIKey

Request body: required.

Content type: application/json. CreateAccessLevel

ResponseMeaning
201Access level created.
400Payload is malformed or fails store validation.
401The required bearer credential is missing, invalid, or revoked.
409The requested identifier or lifecycle transition conflicts with existing state.
503A verifier or durable dependency is temporarily unavailable.

201 application/json body: CatalogAccessLevel

GET /v1/access-levels/{access_level_id}

Operation: getAccessLevel.

Authentication: bearerAPIKey

ParameterLocationRequiredTypeDetails
access_level_idpathYesstringformat: "uuid".
ResponseMeaning
200Access level.
401The required bearer credential is missing, invalid, or revoked.
404The app-scoped resource does not exist.
503A verifier or durable dependency is temporarily unavailable.

200 application/json body: CatalogAccessLevel

PATCH /v1/access-levels/{access_level_id}

Operation: updateAccessLevel. Updates display_name; lookup_key is immutable.

Authentication: bearerAPIKey

ParameterLocationRequiredTypeDetails
access_level_idpathYesstringformat: "uuid".

Request body: required.

Content type: application/json.

json
{
  "type": "object",
  "required": [
    "display_name"
  ],
  "properties": {
    "display_name": {
      "type": "string",
      "maxLength": 512
    }
  },
  "additionalProperties": false
}
ResponseMeaning
200Access level updated.
400Payload is malformed or fails store validation.
401The required bearer credential is missing, invalid, or revoked.
404The app-scoped resource does not exist.
503A verifier or durable dependency is temporarily unavailable.

200 application/json body: CatalogAccessLevel

DELETE /v1/access-levels/{access_level_id}

Operation: archiveAccessLevel. Archives the lookup key and ends active product access mappings without deleting replay history.

Authentication: bearerAPIKey

ParameterLocationRequiredTypeDetails
access_level_idpathYesstringformat: "uuid".
ResponseMeaning
204Access level archived.
401The required bearer credential is missing, invalid, or revoked.
404The app-scoped resource does not exist.
503A verifier or durable dependency is temporarily unavailable.

GET /v1/product-access-mappings

Operation: listProductAccessMappings.

Authentication: bearerAPIKey

ResponseMeaning
200Active Apple and Google product access mappings.
401The required bearer credential is missing, invalid, or revoked.
503A verifier or durable dependency is temporarily unavailable.

200 application/json body:

json
{
  "type": "object",
  "required": [
    "product_mappings"
  ],
  "properties": {
    "product_mappings": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/ProductAccessMapping"
      }
    }
  },
  "additionalProperties": false
}

POST /v1/product-access-mappings

Operation: createProductAccessMapping. Starts a mapping after a short, safe ledger high-water boundary.

Authentication: bearerAPIKey

Request body: required.

Content type: application/json. CreateProductAccessMapping

ResponseMeaning
201Active mapping version.
400Payload is malformed or fails store validation.
401The required bearer credential is missing, invalid, or revoked.
404The app-scoped resource does not exist.
409The requested identifier or lifecycle transition conflicts with existing state.
503A verifier or durable dependency is temporarily unavailable.

201 application/json body: ProductAccessMapping

PATCH /v1/product-access-mappings/{mapping_id}

Operation: updateProductAccessMapping. Ends the active version and starts a new grant-mode version at one ledger boundary.

Authentication: bearerAPIKey

ParameterLocationRequiredTypeDetails
mapping_idpathYesstringformat: "uuid".

Request body: required.

Content type: application/json.

json
{
  "type": "object",
  "required": [
    "grant_mode"
  ],
  "properties": {
    "grant_mode": {
      "$ref": "#/components/schemas/GrantMode"
    }
  },
  "additionalProperties": false
}
ResponseMeaning
200New active mapping version.
400Payload is malformed or fails store validation.
401The required bearer credential is missing, invalid, or revoked.
404The app-scoped resource does not exist.
409The requested identifier or lifecycle transition conflicts with existing state.
503A verifier or durable dependency is temporarily unavailable.

200 application/json body: ProductAccessMapping

DELETE /v1/product-access-mappings/{mapping_id}

Operation: deleteProductAccessMapping. Ends the active version after the current safe ledger head.

Authentication: bearerAPIKey

ParameterLocationRequiredTypeDetails
mapping_idpathYesstringformat: "uuid".
ResponseMeaning
204Mapping version ended.
401The required bearer credential is missing, invalid, or revoked.
404The app-scoped resource does not exist.
503A verifier or durable dependency is temporarily unavailable.

POST /v1/client-tokens

Operation: createClientToken. Requires a secret app key. Mints an opaque, short-lived token binding a publishable-key client to one app_user_id.

Authentication: bearerAPIKey

Request body: required.

Content type: application/json. CreateClientToken

ResponseMeaning
201One-time opaque customer token.
400Payload is malformed or fails store validation.
401The required bearer credential is missing, invalid, or revoked.
403The authenticated key or customer token is not authorized for this resource.
503A verifier or durable dependency is temporarily unavailable.

201 application/json body: CreatedClientToken

Response headers: Cache-Control (const: "no-store".).

DELETE /v1/client-tokens/{token_id}

Operation: revokeClientToken. Requires a secret app key and revokes one app-scoped customer token immediately.

Authentication: bearerAPIKey

ParameterLocationRequiredTypeDetails
token_idpathYesstringformat: "uuid".
ResponseMeaning
204Client token revoked.
401The required bearer credential is missing, invalid, or revoked.
403The authenticated key or customer token is not authorized for this resource.
404The app-scoped resource does not exist.
503A verifier or durable dependency is temporarily unavailable.

Webhook management and delivery

GET /v1/webhook-endpoints

Operation: listWebhookEndpoints.

Authentication: bearerAPIKey

ResponseMeaning
200Non-deleted endpoints for the authenticated app.
401The required bearer credential is missing, invalid, or revoked.
503A verifier or durable dependency is temporarily unavailable.

200 application/json body:

json
{
  "type": "object",
  "required": [
    "endpoints"
  ],
  "properties": {
    "endpoints": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/WebhookEndpoint"
      }
    }
  },
  "additionalProperties": false
}

POST /v1/webhook-endpoints

Operation: createWebhookEndpoint. Creates an HTTPS endpoint and returns its Standard Webhooks signing secret once. Destinations that are literal private or special-purpose addresses are rejected; resolved addresses are checked again on every dial.

Authentication: bearerAPIKey

Request body: required.

Content type: application/json. CreateWebhookEndpoint

ResponseMeaning
201Endpoint and one-time signing secret. The response must not be cached.
400Payload is malformed or fails store validation.
401The required bearer credential is missing, invalid, or revoked.
503A verifier or durable dependency is temporarily unavailable.

201 application/json body: CreatedWebhookEndpoint

Response headers: Cache-Control (const: "no-store".).

GET /v1/webhook-endpoints/{endpoint_id}

Operation: getWebhookEndpoint.

Authentication: bearerAPIKey

ParameterLocationRequiredTypeDetails
endpoint_idpathYesstringformat: "uuid".
ResponseMeaning
200Endpoint configuration without signing material.
401The required bearer credential is missing, invalid, or revoked.
404The app-scoped resource does not exist.
503A verifier or durable dependency is temporarily unavailable.

200 application/json body: WebhookEndpoint

PATCH /v1/webhook-endpoints/{endpoint_id}

Operation: updateWebhookEndpoint.

Authentication: bearerAPIKey

ParameterLocationRequiredTypeDetails
endpoint_idpathYesstringformat: "uuid".

Request body: required.

Content type: application/json. UpdateWebhookEndpoint

ResponseMeaning
200Updated endpoint.
400Payload is malformed or fails store validation.
401The required bearer credential is missing, invalid, or revoked.
404The app-scoped resource does not exist.
503A verifier or durable dependency is temporarily unavailable.

200 application/json body: WebhookEndpoint

DELETE /v1/webhook-endpoints/{endpoint_id}

Operation: deleteWebhookEndpoint. Soft-deletes the endpoint, cancels queued work, and retains delivery history.

Authentication: bearerAPIKey

ParameterLocationRequiredTypeDetails
endpoint_idpathYesstringformat: "uuid".
ResponseMeaning
204Endpoint deleted.
401The required bearer credential is missing, invalid, or revoked.
404The app-scoped resource does not exist.
503A verifier or durable dependency is temporarily unavailable.

POST /v1/webhook-endpoints/{endpoint_id}/rotate-secret

Operation: rotateWebhookEndpointSecret. Returns a new signing secret once and dual-signs with the immediately previous secret for 24 hours.

Authentication: bearerAPIKey

ParameterLocationRequiredTypeDetails
endpoint_idpathYesstringformat: "uuid".
ResponseMeaning
200One-time rotated secret and overlap boundary.
401The required bearer credential is missing, invalid, or revoked.
404The app-scoped resource does not exist.
503A verifier or durable dependency is temporarily unavailable.

200 application/json body: RotatedWebhookSecret

Response headers: Cache-Control (const: "no-store".).

GET /v1/webhook-deliveries

Operation: listWebhookDeliveries.

Authentication: bearerAPIKey

ParameterLocationRequiredTypeDetails
endpoint_idqueryNostringformat: "uuid".
statusqueryNoWebhookDeliveryStatus
before_event_numberqueryNointegerExclusive keyset cursor over the monotonic, non-gapless ledger event number. format: "int64". minimum: 1.
limitqueryNointegerminimum: 1. maximum: 200. default: 50.
ResponseMeaning
200Newest-first delivery history.
400Payload is malformed or fails store validation.
401The required bearer credential is missing, invalid, or revoked.
503A verifier or durable dependency is temporarily unavailable.

200 application/json body:

json
{
  "type": "object",
  "required": [
    "deliveries"
  ],
  "properties": {
    "deliveries": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/WebhookDelivery"
      }
    }
  },
  "additionalProperties": false
}

GET /v1/webhook-deliveries/{message_id}

Operation: getWebhookDelivery.

Authentication: bearerAPIKey

ParameterLocationRequiredTypeDetails
message_idpathYesstringpattern: "^msg_[A-Za-z0-9_-]{20,64}$".
ResponseMeaning
200Delivery and every recorded attempt, including expired worker leases.
401The required bearer credential is missing, invalid, or revoked.
404The app-scoped resource does not exist.
503A verifier or durable dependency is temporarily unavailable.

200 application/json body: WebhookDeliveryDetail

POST /v1/webhook-deliveries/{message_id}/retry

Operation: retryWebhookDelivery. Starts a fresh 72-hour retry cycle for a terminal delivery while retaining its message id and prior attempt history. The endpoint must first be enabled.

Authentication: bearerAPIKey

ParameterLocationRequiredTypeDetails
message_idpathYesstringpattern: "^msg_[A-Za-z0-9_-]{20,64}$".
ResponseMeaning
200Requeued delivery.
400Payload is malformed or fails store validation.
401The required bearer credential is missing, invalid, or revoked.
404The app-scoped resource does not exist.
409Endpoint is disabled or delivery is already queued/in flight.
503A verifier or durable dependency is temporarily unavailable.

200 application/json body: WebhookDelivery

Root operator administration

GET /admin/v1/apps

Operation: listApps.

Authentication: adminBearer

ResponseMeaning
200All active and disabled apps in stable creation order.
401The required bearer credential is missing, invalid, or revoked.
503A verifier or durable dependency is temporarily unavailable.

200 application/json body:

json
{
  "type": "object",
  "required": [
    "apps"
  ],
  "properties": {
    "apps": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/App"
      }
    }
  },
  "additionalProperties": false
}

POST /admin/v1/apps

Operation: createApp. Creates an Apple, Google, or cross-platform app and returns its first API key exactly once.

Authentication: adminBearer

Request body: required.

Content type: application/json. CreateApp

ResponseMeaning
201App, safe key metadata, and one-time plaintext secret.
400Payload is malformed or fails store validation.
401The required bearer credential is missing, invalid, or revoked.
409The requested identifier or lifecycle transition conflicts with existing state.
503A verifier or durable dependency is temporarily unavailable.

201 application/json body: CreatedApp

Response headers: Cache-Control (const: "no-store".).

GET /admin/v1/apps/{app_id}

Operation: getApp.

Authentication: adminBearer

ParameterLocationRequiredTypeDetails
app_idpathYesstringformat: "uuid".
ResponseMeaning
200App configuration.
401The required bearer credential is missing, invalid, or revoked.
404The app-scoped resource does not exist.
503A verifier or durable dependency is temporarily unavailable.

200 application/json body: App

PATCH /admin/v1/apps/{app_id}

Operation: updateApp.

Authentication: adminBearer

ParameterLocationRequiredTypeDetails
app_idpathYesstringformat: "uuid".

Request body: required.

Content type: application/json. UpdateApp

ResponseMeaning
200Updated app. Re-enabling does not un-revoke old keys.
400Payload is malformed or fails store validation.
401The required bearer credential is missing, invalid, or revoked.
404The app-scoped resource does not exist.
409The requested identifier or lifecycle transition conflicts with existing state.
503A verifier or durable dependency is temporarily unavailable.

200 application/json body: App

DELETE /admin/v1/apps/{app_id}

Operation: disableApp. Soft-disables ingestion, revokes all app API keys, disables webhooks, and retains audit history.

Authentication: adminBearer

ParameterLocationRequiredTypeDetails
app_idpathYesstringformat: "uuid".
ResponseMeaning
204App disabled.
401The required bearer credential is missing, invalid, or revoked.
404The app-scoped resource does not exist.
503A verifier or durable dependency is temporarily unavailable.

GET /admin/v1/apps/{app_id}/api-keys

Operation: listAppAPIKeys.

Authentication: adminBearer

ParameterLocationRequiredTypeDetails
app_idpathYesstringformat: "uuid".
ResponseMeaning
200Safe API-key metadata; plaintext keys are never returned.
401The required bearer credential is missing, invalid, or revoked.
404The app-scoped resource does not exist.
503A verifier or durable dependency is temporarily unavailable.

200 application/json body:

json
{
  "type": "object",
  "required": [
    "api_keys"
  ],
  "properties": {
    "api_keys": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/APIKey"
      }
    }
  },
  "additionalProperties": false
}

POST /admin/v1/apps/{app_id}/api-keys

Operation: createAppAPIKey.

Authentication: adminBearer

ParameterLocationRequiredTypeDetails
app_idpathYesstringformat: "uuid".

Request body: required.

Content type: application/json.

json
{
  "type": "object",
  "properties": {
    "label": {
      "type": "string",
      "maxLength": 512
    },
    "kind": {
      "type": "string",
      "enum": [
        "secret",
        "publishable"
      ],
      "default": "secret"
    }
  },
  "additionalProperties": false
}
ResponseMeaning
201Safe metadata and one-time plaintext secret.
400Payload is malformed or fails store validation.
401The required bearer credential is missing, invalid, or revoked.
404The app-scoped resource does not exist.
409The requested identifier or lifecycle transition conflicts with existing state.
503A verifier or durable dependency is temporarily unavailable.

201 application/json body: CreatedAPIKey

Response headers: Cache-Control (const: "no-store".).

DELETE /admin/v1/apps/{app_id}/api-keys/{key_id}

Operation: revokeAppAPIKey.

Authentication: adminBearer

ParameterLocationRequiredTypeDetails
app_idpathYesstringformat: "uuid".
key_idpathYesstringformat: "uuid".
ResponseMeaning
204Key revoked.
401The required bearer credential is missing, invalid, or revoked.
404The app-scoped resource does not exist.
503A verifier or durable dependency is temporarily unavailable.

Incoming store notifications

POST /ingest/apple/assn

Operation: ingestAppleNotification. Verifies an App Store Server Notifications V2 outer and nested JWS values, attributes its app, and atomically appends and projects or rejects it.

Authentication: No app-key security scheme declared; store-ingress verification still applies where described.

Request body: required.

Content type: application/json.

json
{
  "type": "object",
  "required": [
    "signedPayload"
  ],
  "properties": {
    "signedPayload": {
      "type": "string"
    }
  },
  "additionalProperties": false
}
ResponseMeaning
200Delivery appended, deduplicated, or durably rejected.
503PostgreSQL or Apple's OCSP responder is temporarily unavailable.

POST /ingest/google/rtdn

Operation: ingestGoogleNotification. Verifies Pub/Sub OIDC identity, appends the RTDN doorbell, fetches authoritative subscriptionsv2 or productsv2 state when required, and atomically projects all line items.

Authentication: googlePubSubOIDC

Request body: required.

Content type: application/json. PubSubPush

ResponseMeaning
200Delivery appended, deduplicated, or durably rejected.
401The required bearer credential is missing, invalid, or revoked.
403The valid Google identity is not the configured Pub/Sub service account.
503A verifier or durable dependency is temporarily unavailable.

Health and observability

GET /livez

Operation: getLiveness.

Authentication: No app-key security scheme declared; store-ingress verification still applies where described.

ResponseMeaning
200Process is alive.

200 application/json body: Probe

GET /readyz

Operation: getReadiness.

Authentication: No app-key security scheme declared; store-ingress verification still applies where described.

ResponseMeaning
200Process and PostgreSQL are ready.
503PostgreSQL is unavailable.

200 application/json body: Probe

GET /healthz

Operation: getHealth. Compatibility alias for readiness.

Authentication: No app-key security scheme declared; store-ingress verification still applies where described.

ResponseMeaning
200Ready.
503Not ready.

200 application/json body: Probe

GET /metrics

Operation: getMetrics.

Authentication: No app-key security scheme declared; store-ingress verification still applies where described.

ResponseMeaning
200Prometheus exposition.

200 text/plain body:

json
{
  "type": "string"
}

Authentication schemes

googlePubSubOIDC

json
{
  "type": "http",
  "scheme": "bearer",
  "bearerFormat": "Google OIDC ID token"
}

bearerAPIKey

json
{
  "type": "http",
  "scheme": "bearer",
  "bearerFormat": "iap_sk_ secret or iap_pk_ publishable app key"
}

adminBearer

json
{
  "type": "http",
  "scheme": "bearer",
  "bearerFormat": "root admin API key"
}

Request and response models

Fields are listed below. Nested array/object definitions, alternatives, and conditional rules remain in the complete schema following each model when applicable. writeOnly denotes one-time/input secret material; do not assume it can be read back from management lists.

Probe

FieldRequiredTypeDetails
statusYesstringValues: ok, unavailable.
json
{
  "type": "object",
  "required": [
    "status"
  ],
  "properties": {
    "status": {
      "type": "string",
      "enum": [
        "ok",
        "unavailable"
      ]
    }
  },
  "additionalProperties": false
}

PubSubPush

FieldRequiredTypeDetails
messageYesobject
subscriptionNostring
json
{
  "type": "object",
  "required": [
    "message"
  ],
  "properties": {
    "message": {
      "type": "object",
      "required": [
        "data",
        "messageId"
      ],
      "properties": {
        "data": {
          "type": "string",
          "contentEncoding": "base64"
        },
        "messageId": {
          "type": "string"
        },
        "publishTime": {
          "type": "string",
          "format": "date-time"
        },
        "attributes": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        }
      },
      "additionalProperties": true
    },
    "subscription": {
      "type": "string"
    }
  },
  "additionalProperties": true
}

ReceiptSubmission

FieldRequiredTypeDetails
platformYesstringValues: apple, google.
app_user_idYesstringminLength: 1. maxLength: 512.
product_typeNostringRequired for Google; omitted for Apple. Values: subscription, one_time_product.
store_payloadYesstringApple StoreKit transaction jwsRepresentation or Google purchase token.
json
{
  "type": "object",
  "required": [
    "platform",
    "app_user_id",
    "store_payload"
  ],
  "properties": {
    "platform": {
      "type": "string",
      "enum": [
        "apple",
        "google"
      ]
    },
    "app_user_id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 512
    },
    "product_type": {
      "type": "string",
      "enum": [
        "subscription",
        "one_time_product"
      ],
      "description": "Required for Google; omitted for Apple."
    },
    "store_payload": {
      "type": "string",
      "description": "Apple StoreKit transaction jwsRepresentation or Google purchase token."
    }
  },
  "additionalProperties": false,
  "allOf": [
    {
      "if": {
        "properties": {
          "platform": {
            "const": "google"
          }
        }
      },
      "then": {
        "required": [
          "product_type"
        ]
      }
    }
  ]
}

IngestResult

FieldRequiredTypeDetails
event_idYesstringPositive decimal int64 ledger id (maximum 9223372036854775807) encoded as a string for lossless JavaScript and Dart interoperability. maxLength: 19. pattern: "^[1-9][0-9]*$".
deduplicatedYesboolean
json
{
  "type": "object",
  "required": [
    "event_id",
    "deduplicated"
  ],
  "properties": {
    "event_id": {
      "type": "string",
      "pattern": "^[1-9][0-9]*$",
      "maxLength": 19,
      "description": "Positive decimal int64 ledger id (maximum 9223372036854775807) encoded as a string for lossless JavaScript and Dart interoperability."
    },
    "deduplicated": {
      "type": "boolean"
    }
  },
  "additionalProperties": false
}

Subscriber

FieldRequiredTypeDetails
app_user_idYesstring
customer_idYesstringformat: "uuid".
access_levelsYesobject
json
{
  "type": "object",
  "required": [
    "app_user_id",
    "customer_id",
    "access_levels"
  ],
  "properties": {
    "app_user_id": {
      "type": "string"
    },
    "customer_id": {
      "type": "string",
      "format": "uuid"
    },
    "access_levels": {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/components/schemas/SubscriberAccessLevel"
      }
    }
  },
  "additionalProperties": false
}

SubscriberAccessLevel

FieldRequiredTypeDetails
activeYesboolean
expires_atNostringformat: "date-time".
platformYesstringValues: apple, google.
product_idYesstring
last_verified_atYesstringformat: "date-time".
event_idYesstringPositive decimal int64 ledger id (maximum 9223372036854775807) encoded as a string for lossless JavaScript and Dart interoperability. maxLength: 19. pattern: "^[1-9][0-9]*$".
json
{
  "type": "object",
  "required": [
    "active",
    "platform",
    "product_id",
    "last_verified_at",
    "event_id"
  ],
  "properties": {
    "active": {
      "type": "boolean"
    },
    "expires_at": {
      "type": "string",
      "format": "date-time"
    },
    "platform": {
      "type": "string",
      "enum": [
        "apple",
        "google"
      ]
    },
    "product_id": {
      "type": "string"
    },
    "last_verified_at": {
      "type": "string",
      "format": "date-time"
    },
    "event_id": {
      "type": "string",
      "pattern": "^[1-9][0-9]*$",
      "maxLength": 19,
      "description": "Positive decimal int64 ledger id (maximum 9223372036854775807) encoded as a string for lossless JavaScript and Dart interoperability."
    }
  },
  "additionalProperties": false
}

CurrentProductSet

FieldRequiredTypeDetails
product_setYesunion
json
{
  "type": "object",
  "required": [
    "product_set"
  ],
  "properties": {
    "product_set": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/ProductSet"
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "additionalProperties": false
}

ProductSet

FieldRequiredTypeDetails
idYesstringformat: "uuid".
identifierYesstringminLength: 1. maxLength: 128. pattern: "^[A-Za-z0-9._-]+$".
display_nameYesstringminLength: 1. maxLength: 256.
packagesYesarray of ProductSetPackageOrdered by ascending position; identifiers and positions are unique within the set.
updated_atYesstringformat: "date-time".
json
{
  "type": "object",
  "required": [
    "id",
    "identifier",
    "display_name",
    "packages",
    "updated_at"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "identifier": {
      "type": "string",
      "minLength": 1,
      "maxLength": 128,
      "pattern": "^[A-Za-z0-9._-]+$"
    },
    "display_name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 256
    },
    "packages": {
      "type": "array",
      "description": "Ordered by ascending position; identifiers and positions are unique within the set.",
      "items": {
        "$ref": "#/components/schemas/ProductSetPackage"
      }
    },
    "updated_at": {
      "type": "string",
      "format": "date-time"
    }
  },
  "additionalProperties": false
}

ProductSetPackage

FieldRequiredTypeDetails
idYesstringformat: "uuid".
identifierYesstringminLength: 1. maxLength: 128. pattern: "^[A-Za-z0-9._-]+$".
package_typeYesstringValues: custom, lifetime, annual, six_month, three_month, two_month, monthly, weekly.
platformYesstringValues: apple, google.
product_idYesstringminLength: 1. maxLength: 512.
base_plan_idNostringOptional Google Play base-plan identifier. Present only for Google packages; preserve it when selecting a storefront offer. minLength: 1. maxLength: 128. pattern: "^[A-Za-z0-9._-]+$".
positionYesintegerminimum: 0. maximum: 1000.
json
{
  "type": "object",
  "required": [
    "id",
    "identifier",
    "package_type",
    "platform",
    "product_id",
    "position"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "identifier": {
      "type": "string",
      "minLength": 1,
      "maxLength": 128,
      "pattern": "^[A-Za-z0-9._-]+$"
    },
    "package_type": {
      "type": "string",
      "enum": [
        "custom",
        "lifetime",
        "annual",
        "six_month",
        "three_month",
        "two_month",
        "monthly",
        "weekly"
      ]
    },
    "platform": {
      "type": "string",
      "enum": [
        "apple",
        "google"
      ]
    },
    "product_id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 512
    },
    "base_plan_id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 128,
      "pattern": "^[A-Za-z0-9._-]+$",
      "description": "Optional Google Play base-plan identifier. Present only for Google packages; preserve it when selecting a storefront offer."
    },
    "position": {
      "type": "integer",
      "minimum": 0,
      "maximum": 1000
    }
  },
  "additionalProperties": false
}

WebhookEndpoint

FieldRequiredTypeDetails
idYesstringformat: "uuid".
urlYesstringformat: "uri". maxLength: 2048.
descriptionYesstringmaxLength: 512.
event_typesYesarray of string
enabledYesboolean
disabled_reasonNostringmaxLength: 512.
disabled_atNostringformat: "date-time".
created_atYesstringformat: "date-time".
updated_atYesstringformat: "date-time".
json
{
  "type": "object",
  "required": [
    "id",
    "url",
    "description",
    "event_types",
    "enabled",
    "created_at",
    "updated_at"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "url": {
      "type": "string",
      "format": "uri",
      "maxLength": 2048
    },
    "description": {
      "type": "string",
      "maxLength": 512
    },
    "event_types": {
      "type": "array",
      "minItems": 1,
      "maxItems": 100,
      "uniqueItems": true,
      "items": {
        "type": "string"
      }
    },
    "enabled": {
      "type": "boolean"
    },
    "disabled_reason": {
      "type": "string",
      "maxLength": 512
    },
    "disabled_at": {
      "type": "string",
      "format": "date-time"
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time"
    }
  },
  "additionalProperties": false
}

CreateWebhookEndpoint

FieldRequiredTypeDetails
urlYesstringformat: "uri". maxLength: 2048. pattern: "^https://".
descriptionNostringmaxLength: 512.
event_typesNoarray of stringdefault: ["access.changed"].
json
{
  "type": "object",
  "required": [
    "url"
  ],
  "properties": {
    "url": {
      "type": "string",
      "format": "uri",
      "pattern": "^https://",
      "maxLength": 2048
    },
    "description": {
      "type": "string",
      "maxLength": 512
    },
    "event_types": {
      "type": "array",
      "minItems": 1,
      "maxItems": 100,
      "uniqueItems": true,
      "default": [
        "access.changed"
      ],
      "items": {
        "type": "string"
      }
    }
  },
  "additionalProperties": false
}

UpdateWebhookEndpoint

FieldRequiredTypeDetails
urlNostringformat: "uri". maxLength: 2048. pattern: "^https://".
descriptionNostringmaxLength: 512.
event_typesNoarray of string
enabledNoboolean
json
{
  "type": "object",
  "minProperties": 1,
  "properties": {
    "url": {
      "type": "string",
      "format": "uri",
      "pattern": "^https://",
      "maxLength": 2048
    },
    "description": {
      "type": "string",
      "maxLength": 512
    },
    "event_types": {
      "type": "array",
      "minItems": 1,
      "maxItems": 100,
      "uniqueItems": true,
      "items": {
        "type": "string"
      }
    },
    "enabled": {
      "type": "boolean"
    }
  },
  "additionalProperties": false
}

CreatedWebhookEndpoint

FieldRequiredTypeDetails
endpointYesWebhookEndpoint
secretYesstringpattern: "^whsec_". writeOnly: true.
json
{
  "type": "object",
  "required": [
    "endpoint",
    "secret"
  ],
  "properties": {
    "endpoint": {
      "$ref": "#/components/schemas/WebhookEndpoint"
    },
    "secret": {
      "type": "string",
      "pattern": "^whsec_",
      "writeOnly": true
    }
  },
  "additionalProperties": false
}

RotatedWebhookSecret

FieldRequiredTypeDetails
endpoint_idYesstringformat: "uuid".
secretYesstringpattern: "^whsec_". writeOnly: true.
rotated_atYesstringformat: "date-time".
overlap_ends_atYesstringformat: "date-time".
json
{
  "type": "object",
  "required": [
    "endpoint_id",
    "secret",
    "rotated_at",
    "overlap_ends_at"
  ],
  "properties": {
    "endpoint_id": {
      "type": "string",
      "format": "uuid"
    },
    "secret": {
      "type": "string",
      "pattern": "^whsec_",
      "writeOnly": true
    },
    "rotated_at": {
      "type": "string",
      "format": "date-time"
    },
    "overlap_ends_at": {
      "type": "string",
      "format": "date-time"
    }
  },
  "additionalProperties": false
}

WebhookDeliveryStatus

json
{
  "type": "string",
  "enum": [
    "pending",
    "in_flight",
    "retry",
    "succeeded",
    "dead_letter",
    "canceled"
  ]
}

WebhookDelivery

FieldRequiredTypeDetails
message_idYesstringpattern: "^msg_[A-Za-z0-9_-]{20,64}$".
endpoint_idYesstringformat: "uuid".
event_numberYesintegerformat: "int64".
event_typeYesstring
statusYesWebhookDeliveryStatus
attempt_countYesintegerminimum: 0.
next_attempt_atNostringformat: "date-time".
first_attempt_atNostringformat: "date-time".
last_attempt_atNostringformat: "date-time".
succeeded_atNostringformat: "date-time".
last_http_statusNointegerminimum: 100. maximum: 599.
last_errorNostringmaxLength: 2048.
last_response_bodyNostringUTF-8-safe preview capped at 64 KiB.
cycle_started_atYesstringformat: "date-time".
created_atYesstringformat: "date-time".
updated_atYesstringformat: "date-time".
json
{
  "type": "object",
  "required": [
    "message_id",
    "endpoint_id",
    "event_number",
    "event_type",
    "status",
    "attempt_count",
    "cycle_started_at",
    "created_at",
    "updated_at"
  ],
  "properties": {
    "message_id": {
      "type": "string",
      "pattern": "^msg_[A-Za-z0-9_-]{20,64}$"
    },
    "endpoint_id": {
      "type": "string",
      "format": "uuid"
    },
    "event_number": {
      "type": "integer",
      "format": "int64"
    },
    "event_type": {
      "type": "string"
    },
    "status": {
      "$ref": "#/components/schemas/WebhookDeliveryStatus"
    },
    "attempt_count": {
      "type": "integer",
      "minimum": 0
    },
    "next_attempt_at": {
      "type": "string",
      "format": "date-time"
    },
    "first_attempt_at": {
      "type": "string",
      "format": "date-time"
    },
    "last_attempt_at": {
      "type": "string",
      "format": "date-time"
    },
    "succeeded_at": {
      "type": "string",
      "format": "date-time"
    },
    "last_http_status": {
      "type": "integer",
      "minimum": 100,
      "maximum": 599
    },
    "last_error": {
      "type": "string",
      "maxLength": 2048
    },
    "last_response_body": {
      "type": "string",
      "description": "UTF-8-safe preview capped at 64 KiB."
    },
    "cycle_started_at": {
      "type": "string",
      "format": "date-time"
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time"
    }
  },
  "additionalProperties": false
}

WebhookDeliveryAttempt

FieldRequiredTypeDetails
attempt_numberYesintegerminimum: 1.
started_atYesstringformat: "date-time".
finished_atNostringformat: "date-time".
http_statusNointegerminimum: 100. maximum: 599.
errorNostringmaxLength: 2048.
response_bodyNostring
duration_msNointegerformat: "int64". minimum: 0.
succeededNoboolean
json
{
  "type": "object",
  "required": [
    "attempt_number",
    "started_at"
  ],
  "properties": {
    "attempt_number": {
      "type": "integer",
      "minimum": 1
    },
    "started_at": {
      "type": "string",
      "format": "date-time"
    },
    "finished_at": {
      "type": "string",
      "format": "date-time"
    },
    "http_status": {
      "type": "integer",
      "minimum": 100,
      "maximum": 599
    },
    "error": {
      "type": "string",
      "maxLength": 2048
    },
    "response_body": {
      "type": "string"
    },
    "duration_ms": {
      "type": "integer",
      "format": "int64",
      "minimum": 0
    },
    "succeeded": {
      "type": "boolean"
    }
  },
  "additionalProperties": false
}

WebhookDeliveryDetail

FieldRequiredTypeDetails
deliveryYesWebhookDelivery
attemptsYesarray of WebhookDeliveryAttempt
json
{
  "type": "object",
  "required": [
    "delivery",
    "attempts"
  ],
  "properties": {
    "delivery": {
      "$ref": "#/components/schemas/WebhookDelivery"
    },
    "attempts": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/WebhookDeliveryAttempt"
      }
    }
  },
  "additionalProperties": false
}

OutboundWebhookEvent

Exact JSON body signed using Standard Webhooks headers.

FieldRequiredTypeDetails
idYesstringpattern: "^evt_[0-9]+$".
typeYesstring
api_versionYesstringconst: "2026-08-28".
timestampYesstringformat: "date-time".
event_numberYesintegerMonotonic but not gapless ledger identifier. format: "int64".
dataYesobject
json
{
  "type": "object",
  "description": "Exact JSON body signed using Standard Webhooks headers.",
  "required": [
    "id",
    "type",
    "api_version",
    "timestamp",
    "event_number",
    "data"
  ],
  "properties": {
    "id": {
      "type": "string",
      "pattern": "^evt_[0-9]+$"
    },
    "type": {
      "type": "string",
      "example": "access.changed"
    },
    "api_version": {
      "type": "string",
      "const": "2026-08-28"
    },
    "timestamp": {
      "type": "string",
      "format": "date-time"
    },
    "event_number": {
      "type": "integer",
      "format": "int64",
      "description": "Monotonic but not gapless ledger identifier."
    },
    "data": {
      "type": "object",
      "additionalProperties": true
    }
  },
  "additionalProperties": false
}

App

FieldRequiredTypeDetails
idYesstringformat: "uuid".
nameYesstringminLength: 1. maxLength: 512.
apple_bundle_idNostringminLength: 1. maxLength: 512.
apple_app_apple_idNointegerformat: "int64". minimum: 1.
google_package_nameNostringminLength: 1. maxLength: 512.
enabledYesboolean
disabled_atNostringformat: "date-time".
created_atYesstringformat: "date-time".
updated_atYesstringformat: "date-time".
json
{
  "type": "object",
  "required": [
    "id",
    "name",
    "enabled",
    "created_at",
    "updated_at"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 512
    },
    "apple_bundle_id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 512
    },
    "apple_app_apple_id": {
      "type": "integer",
      "format": "int64",
      "minimum": 1
    },
    "google_package_name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 512
    },
    "enabled": {
      "type": "boolean"
    },
    "disabled_at": {
      "type": "string",
      "format": "date-time"
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time"
    }
  },
  "additionalProperties": false
}

CreateApp

FieldRequiredTypeDetails
nameYesstringminLength: 1. maxLength: 512.
apple_bundle_idNostringminLength: 1. maxLength: 512.
apple_app_apple_idNointegerRequired for production Apple notification attribution. format: "int64". minimum: 1.
google_package_nameNostringminLength: 1. maxLength: 512.
initial_key_labelNostringmaxLength: 512. default: "default".
json
{
  "type": "object",
  "required": [
    "name"
  ],
  "anyOf": [
    {
      "required": [
        "apple_bundle_id"
      ]
    },
    {
      "required": [
        "google_package_name"
      ]
    }
  ],
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 512
    },
    "apple_bundle_id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 512
    },
    "apple_app_apple_id": {
      "type": "integer",
      "format": "int64",
      "minimum": 1,
      "description": "Required for production Apple notification attribution."
    },
    "google_package_name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 512
    },
    "initial_key_label": {
      "type": "string",
      "maxLength": 512,
      "default": "default"
    }
  },
  "additionalProperties": false
}

UpdateApp

FieldRequiredTypeDetails
nameNostringminLength: 1. maxLength: 512.
apple_bundle_idNostring or nullminLength: 1. maxLength: 512.
apple_app_apple_idNointeger or nullformat: "int64". minimum: 1.
google_package_nameNostring or nullminLength: 1. maxLength: 512.
enabledNoboolean
json
{
  "type": "object",
  "minProperties": 1,
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 512
    },
    "apple_bundle_id": {
      "type": [
        "string",
        "null"
      ],
      "minLength": 1,
      "maxLength": 512
    },
    "apple_app_apple_id": {
      "type": [
        "integer",
        "null"
      ],
      "format": "int64",
      "minimum": 1
    },
    "google_package_name": {
      "type": [
        "string",
        "null"
      ],
      "minLength": 1,
      "maxLength": 512
    },
    "enabled": {
      "type": "boolean"
    }
  },
  "additionalProperties": false
}

APIKey

FieldRequiredTypeDetails
idYesstringformat: "uuid".
kindYesstringValues: secret, publishable.
labelYesstringmaxLength: 512.
hintYesstringmaxLength: 80.
created_atYesstringformat: "date-time".
revoked_atNostringformat: "date-time".
json
{
  "type": "object",
  "required": [
    "id",
    "kind",
    "label",
    "hint",
    "created_at"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "kind": {
      "type": "string",
      "enum": [
        "secret",
        "publishable"
      ]
    },
    "label": {
      "type": "string",
      "maxLength": 512
    },
    "hint": {
      "type": "string",
      "maxLength": 80
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    },
    "revoked_at": {
      "type": "string",
      "format": "date-time"
    }
  },
  "additionalProperties": false
}

CreatedAPIKey

FieldRequiredTypeDetails
api_keyYesAPIKey
secretYesstringpattern: "^iap_(sk|pk)_". writeOnly: true.
json
{
  "type": "object",
  "required": [
    "api_key",
    "secret"
  ],
  "properties": {
    "api_key": {
      "$ref": "#/components/schemas/APIKey"
    },
    "secret": {
      "type": "string",
      "pattern": "^iap_(sk|pk)_",
      "writeOnly": true
    }
  },
  "additionalProperties": false
}

CreatedApp

FieldRequiredTypeDetails
appYesApp
api_keyYesAPIKey
secretYesstringpattern: "^iap_sk_". writeOnly: true.
json
{
  "type": "object",
  "required": [
    "app",
    "api_key",
    "secret"
  ],
  "properties": {
    "app": {
      "$ref": "#/components/schemas/App"
    },
    "api_key": {
      "$ref": "#/components/schemas/APIKey"
    },
    "secret": {
      "type": "string",
      "pattern": "^iap_sk_",
      "writeOnly": true
    }
  },
  "additionalProperties": false
}

CatalogAccessLevel

FieldRequiredTypeDetails
idYesstringformat: "uuid".
lookup_keyYesstringpattern: "^[A-Za-z0-9][A-Za-z0-9._-]{0,254}$".
display_nameYesstringmaxLength: 512.
created_atYesstringformat: "date-time".
updated_atYesstringformat: "date-time".
json
{
  "type": "object",
  "required": [
    "id",
    "lookup_key",
    "display_name",
    "created_at",
    "updated_at"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "lookup_key": {
      "type": "string",
      "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,254}$"
    },
    "display_name": {
      "type": "string",
      "maxLength": 512
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time"
    }
  },
  "additionalProperties": false
}

CreateAccessLevel

FieldRequiredTypeDetails
lookup_keyYesstringpattern: "^[A-Za-z0-9][A-Za-z0-9._-]{0,254}$".
display_nameNostringmaxLength: 512.
json
{
  "type": "object",
  "required": [
    "lookup_key"
  ],
  "properties": {
    "lookup_key": {
      "type": "string",
      "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,254}$"
    },
    "display_name": {
      "type": "string",
      "maxLength": 512
    }
  },
  "additionalProperties": false
}

GrantMode

json
{
  "type": "string",
  "enum": [
    "store_managed",
    "lifetime"
  ]
}

ProductAccessMapping

FieldRequiredTypeDetails
idYesstringformat: "uuid".
platformYesstringValues: apple, google.
product_idYesstringminLength: 1. maxLength: 512.
access_level_idYesstringformat: "uuid".
access_level_keyYesstring
grant_modeYesGrantMode
starts_after_event_idYesintegerMapping applies to source events with a greater ledger id. format: "int64". minimum: 0.
created_atYesstringformat: "date-time".
json
{
  "type": "object",
  "required": [
    "id",
    "platform",
    "product_id",
    "access_level_id",
    "access_level_key",
    "grant_mode",
    "starts_after_event_id",
    "created_at"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "platform": {
      "type": "string",
      "enum": [
        "apple",
        "google"
      ]
    },
    "product_id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 512
    },
    "access_level_id": {
      "type": "string",
      "format": "uuid"
    },
    "access_level_key": {
      "type": "string"
    },
    "grant_mode": {
      "$ref": "#/components/schemas/GrantMode"
    },
    "starts_after_event_id": {
      "type": "integer",
      "format": "int64",
      "minimum": 0,
      "description": "Mapping applies to source events with a greater ledger id."
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    }
  },
  "additionalProperties": false
}

CreateProductAccessMapping

FieldRequiredTypeDetails
platformYesstringValues: apple, google.
product_idYesstringminLength: 1. maxLength: 512.
access_level_idYesstringformat: "uuid".
grant_modeNoGrantMode
json
{
  "type": "object",
  "required": [
    "platform",
    "product_id",
    "access_level_id"
  ],
  "properties": {
    "platform": {
      "type": "string",
      "enum": [
        "apple",
        "google"
      ]
    },
    "product_id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 512
    },
    "access_level_id": {
      "type": "string",
      "format": "uuid"
    },
    "grant_mode": {
      "$ref": "#/components/schemas/GrantMode"
    }
  },
  "additionalProperties": false
}

CreateClientToken

FieldRequiredTypeDetails
app_user_idYesstringminLength: 1. maxLength: 512.
ttl_secondsNointegerformat: "int64". minimum: 300. maximum: 86400. default: 3600.
json
{
  "type": "object",
  "required": [
    "app_user_id"
  ],
  "properties": {
    "app_user_id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 512
    },
    "ttl_seconds": {
      "type": "integer",
      "format": "int64",
      "minimum": 300,
      "maximum": 86400,
      "default": 3600
    }
  },
  "additionalProperties": false
}

CreatedClientToken

FieldRequiredTypeDetails
idYesstringformat: "uuid".
app_user_idYesstringminLength: 1. maxLength: 512.
hintYesstringmaxLength: 80.
expires_atYesstringformat: "date-time".
tokenYesstringpattern: "^iap_ct_". writeOnly: true.
json
{
  "type": "object",
  "required": [
    "id",
    "app_user_id",
    "hint",
    "expires_at",
    "token"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "app_user_id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 512
    },
    "hint": {
      "type": "string",
      "maxLength": 80
    },
    "expires_at": {
      "type": "string",
      "format": "date-time"
    },
    "token": {
      "type": "string",
      "pattern": "^iap_ct_",
      "writeOnly": true
    }
  },
  "additionalProperties": false
}

Error

FieldRequiredTypeDetails
errorYesstring
json
{
  "type": "object",
  "required": [
    "error"
  ],
  "properties": {
    "error": {
      "type": "string"
    }
  },
  "additionalProperties": false
}

Shared error responses

InvalidRequest

Payload is malformed or fails store validation.

json
{
  "description": "Payload is malformed or fails store validation.",
  "content": {
    "application/json": {
      "schema": {
        "$ref": "#/components/schemas/Error"
      }
    }
  }
}

Unauthorized

The required bearer credential is missing, invalid, or revoked.

json
{
  "description": "The required bearer credential is missing, invalid, or revoked.",
  "headers": {
    "WWW-Authenticate": {
      "schema": {
        "type": "string"
      }
    }
  },
  "content": {
    "application/json": {
      "schema": {
        "$ref": "#/components/schemas/Error"
      }
    }
  }
}

TooLarge

Request exceeds 256 KiB.

json
{
  "description": "Request exceeds 256 KiB.",
  "content": {
    "application/json": {
      "schema": {
        "$ref": "#/components/schemas/Error"
      }
    }
  }
}

RateLimited

The authenticated API key exceeded its process-local receipt rate limit.

json
{
  "description": "The authenticated API key exceeded its process-local receipt rate limit.",
  "headers": {
    "Retry-After": {
      "schema": {
        "type": "string"
      }
    }
  },
  "content": {
    "application/json": {
      "schema": {
        "$ref": "#/components/schemas/Error"
      }
    }
  }
}

Unavailable

A verifier or durable dependency is temporarily unavailable.

json
{
  "description": "A verifier or durable dependency is temporarily unavailable.",
  "headers": {
    "Retry-After": {
      "schema": {
        "type": "string"
      }
    }
  },
  "content": {
    "application/json": {
      "schema": {
        "$ref": "#/components/schemas/Error"
      }
    }
  }
}

NotFound

The app-scoped resource does not exist.

json
{
  "description": "The app-scoped resource does not exist.",
  "content": {
    "application/json": {
      "schema": {
        "$ref": "#/components/schemas/Error"
      }
    }
  }
}

Conflict

The requested identifier or lifecycle transition conflicts with existing state.

json
{
  "description": "The requested identifier or lifecycle transition conflicts with existing state.",
  "content": {
    "application/json": {
      "schema": {
        "$ref": "#/components/schemas/Error"
      }
    }
  }
}

Forbidden

The authenticated key or customer token is not authorized for this resource.

json
{
  "description": "The authenticated key or customer token is not authorized for this resource.",
  "content": {
    "application/json": {
      "schema": {
        "$ref": "#/components/schemas/Error"
      }
    }
  }
}