Skip to content
Indiana
Dashboard
Docs
Browse docs / Request conventions

Request conventions

API endpoint, headers, credentials, idempotent retries and the error format.

API v1Updated

Endpoint and path

The production API is https://api.tinker.cash and the development/test API is https://api.dev.tinker.cash. Every operation lives under /api/v1/; ordinary operations each have a path, and Funnel commands share POST /api/v1/funnels.

request.httpShell
POST https://api.tinker.cash/api/v1/customers/getAuthorization: Bearer <SERVER_KEY>X-Indiana-Protocol: 0.6Content-Type: application/json { "lookup": { "type": "externalUserId", "value": "user-42" } }

Headers

Headers
HeaderRequirement
AuthorizationExactly one Bearer <credential>.
X-Indiana-ProtocolRequired: 0.6. Missing or unsupported values return 400 UNSUPPORTED_PROTOCOL_VERSION.
Content-TypeUse application/json for non-GET requests.
X-Indiana-Project / X-Indiana-EnvironmentOptional scope assertions, sent together: the App UUID and sandbox/live. They must match the credential and cannot select another tenant.
X-Indiana-SDK-VersionOptional; sent by the SDKs.
OriginMust be absent on Server Key requests; browser origins must be registered in Console.

Headers

  • Authorization

    Requirement
    Exactly one Bearer <credential>.
  • X-Indiana-Protocol

    Requirement
    Required: 0.6. Missing or unsupported values return 400 UNSUPPORTED_PROTOCOL_VERSION.
  • Content-Type

    Requirement
    Use application/json for non-GET requests.
  • X-Indiana-Project / X-Indiana-Environment

    Requirement
    Optional scope assertions, sent together: the App UUID and sandbox/live. They must match the credential and cannot select another tenant.
  • X-Indiana-SDK-Version

    Requirement
    Optional; sent by the SDKs.
  • Origin

    Requirement
    Must be absent on Server Key requests; browser origins must be registered in Console.
  • GET operations accept no body or query parameters; other operations reject query parameters too.
  • Successful responses include requestId and scope, with X-Request-Id and Cache-Control: no-store. Success is normally HTTP 200; submitUsageBatch and pending Funnel decisions return 202.

Credentials

Credential types
CredentialPrefixHolderUse
Server Keygg_sk_Your backendServer operations within the Key's App, environment and scopes.
Customer Tokengg_ct_Browser / appCustomer-allowed operations as exactly one Customer.
Run Tokengg_fr_Browser / app / backendOnly its own Funnel Run, with the original identity proof.
Environment UUID—PublicRead published public configuration and website experiments; authenticates nothing.

Credential types

  • Server Key

    Prefix
    gg_sk_
    Holder
    Your backend
    Use
    Server operations within the Key's App, environment and scopes.
  • Customer Token

    Prefix
    gg_ct_
    Holder
    Browser / app
    Use
    Customer-allowed operations as exactly one Customer.
  • Run Token

    Prefix
    gg_fr_
    Holder
    Browser / app / backend
    Use
    Only its own Funnel Run, with the original identity proof.
  • Environment UUID

    Prefix
    —
    Holder
    Public
    Use
    Read published public configuration and website experiments; authenticates nothing.

Every call checks the credential, scope, App/environment/Customer and origin. A Customer Token cannot select another Customer; a Server Key proves backend access, not end-user identity.

Related: Scope list

Idempotency and retries

  • Writes carry a business ID: requestId, eventId or idempotencyKey. Generate and persist it before the first send, and replay the same ID with identical input after an unknown result; reusing an ID with different input returns CONFLICT (IDEMPOTENCY_CONFLICT).
  • The response requestId and X-Request-Id identify one HTTP attempt for diagnostics; never use them as the business ID.
  • Asynchronous work (purchases, changes, refunds, invoices, usage batches, Funnel decisions) returns an operation ID; after a timeout, read the original operation rather than creating a second one.

Error format

error.jsonJSON
{  "requestId": "<HTTP_ATTEMPT_ID>",  "error": {    "code": "FORBIDDEN",    "message": "This credential cannot perform this operation.",    "retryable": false,    "recovery": "check_permissions"  }}

Handle failures by error.code, retryable and recovery; never parse message. error.reason is optional, and Retry-After (seconds) is set when you should wait.

Related: Error codes and recovery