Runtime/API

Direct HTTP reference for SDK authors and advanced integrations.

Most games should start with SDK simple saves. Use this reference when you need direct session control, OpenAPI parity, or custom wrapper behavior.

advancedOpenAPIHTTP

Reference Map

Jump to the operations and contract artifacts advanced integrations usually need first.

Use these previews for direct HTTP work, SDK wrapper implementation, and payload-level debugging.

Use This Page When

This is the direct HTTP reference, not the easiest game integration path.

Game code should normally start with SDK simple game saves. Use this page when you are building an SDK wrapper, validating OpenAPI parity, debugging HTTP traffic, or integrating without an SDK.

Normal Path

Most games should use the account-scoped runtime flow.

This keeps shipped clients scoped to one account session and its slots instead of exposing broad save lookup semantics.

Create an account with the first slot.

Load that account through X-Persistly-Account-Session.

Sync account-owned slots through account-scoped slot routes.

Endpoints

The public runtime contract is intentionally small.

GET/healthz

Lightweight operational health endpoint for uptime checks and deployment verification.

200 OK
GET/api/v1/runtime-config

Return the runtime sync policy plus the active environment game config. Pass gameConfigVersion to skip downloading unchanged config payloads.

200 OK401 Unauthorized429 Too Many Requests
POST/api/v1/accounts

Create one account, one optional initial slot, and one account session token.

201 Created400 Bad Request401 Unauthorized413 Payload Too Large429 Too Many Requests
GET/api/v1/accounts/{accountId}

Load the canonical account state using X-Persistly-Account-Session.

200 OK401 Unauthorized403 Forbidden404 Not Found429 Too Many Requests
POST/api/v1/accounts/{accountId}/transfer-codes

Create a short-lived, single-use transfer code from an existing account session.

201 Created400 Bad Request401 Unauthorized403 Forbidden402 Payment Required410 Gone429 Too Many Requests
POST/api/v1/account-transfer-codes/consume

Consume a transfer code with only the runtime key and receive a new account session for the same account.

200 OK400 Bad Request401 Unauthorized402 Payment Required410 Gone429 Too Many Requests
POST/api/v1/accounts/{accountId}/slots

Create another named slot owned by the current account session.

201 Created400 Bad Request401 Unauthorized403 Forbidden413 Payload Too Large429 Too Many Requests
GET/api/v1/accounts/{accountId}/slots/{slotId}

Load a named slot only when it belongs to the current account session.

200 OK401 Unauthorized403 Forbidden404 Not Found429 Too Many Requests
POST/api/v1/accounts/{accountId}/slots/{slotId}/sync

Sync an account-owned named slot with optimistic concurrency and account-session scoping.

200 OK409 Conflict400 Bad Request401 Unauthorized403 Forbidden404 Not Found413 Payload Too Large429 Too Many Requests

Exact Examples

Use operation-specific example pages when you need copy-pasteable request and response shapes.

These pages exist so developers and coding agents can implement one operation at a time without inferring missing fields or statuses.

Create account

Exact request and response with accountId, accountSessionToken, syncPolicy, account data, and first slot.

Sync slot

Exact account-scoped slot sync request using X-Persistly-Account-Session.

Transfer code

Exact create and consume requests for short-lived anonymous account transfer.

Conflict response

Exact 409 response and recovery model for retrying from the canonical server version.

Error response

Exact structured error envelope with HTTP status, error.code, message, and details.

Auth Boundary

The public runtime is intentionally smaller than the operator/admin surface.

The API is permanent and public-facing for SDK traffic, but that does not mean every operation belongs in the public client path.

Runtime keys identify the environment for SDK traffic. They are not privileged admin credentials.

Account sessions authorize one account and its named slots. Store accountSessionToken like player save data, not like a public lookup value.

Clients should never use runtime keys to discover arbitrary accounts or saves by playerRef.

Trusted lookup by external auth provider belongs to future server-side/operator flows, not the public runtime API.

If an anonymous game still has a valid account session on one device, it can create a short-lived transfer code for another device.

If an anonymous game loses every account session, Persistly cannot safely recover that account from the public runtime API.

If your game already has accounts, store accountId and accountSessionToken in your trusted backend keyed by your authenticated user.

Username lookup, playerRef lookup, external provider token exchange, and Persistly-owned Auth are separate future layers.

Operational Limits

Payload caps and auth rules are part of the contract, not just suggestions.

Data payload256 KB to 2 MB by plan
SlotInfo payload16 KB to 128 KB by plan
Workspace storage1 GB to 500 GB by plan
Restore history24h to 90 days by plan
Conflict modelOptimistic concurrency
Runtime authBearer runtime key

Errors

Clients should treat HTTP status and error code as one contract.

HTTP 400invalid_request

The request body, parameters, or payload shape is invalid for the runtime contract.

HTTP 401unauthorized

The runtime key is missing, malformed, revoked, or does not belong to the target environment.

HTTP 403forbidden

The account session token is missing, invalid, expired, revoked, or does not belong to the requested account or slot.

HTTP 404not_found

The referenced account or slot does not exist in the environment identified by the runtime key.

HTTP 409conflict

The submitted baseVersion is stale. Persistly returns local/cloud branches so the client can reconcile.

HTTP 413payload_too_large

The slotInfo or data payload exceeds Persistly's documented byte limits.

HTTP 402monthly_quota_exceeded

The workspace has exhausted its monthly runtime request quota for the current plan.

HTTP 429rate_limited

The client exceeded allowed request volume for the current environment or plan.

HTTP 400transfer_code_invalid

The transfer code is malformed, unknown, revoked, or belongs to a different environment.

HTTP 400transfer_code_expired

The transfer code has passed its short expiration window. Create a new code from the original device.

HTTP 400transfer_code_consumed

The transfer code was already used. Transfer codes are single-use.

HTTP 429transfer_code_rate_limited

Too many attempts were made against a real transfer code. Create a new code from the original device.

HTTP 400transfer_code_disabled

Transfer codes are not enabled for the current API deployment.

HTTP 500server_error

Persistly failed internally and the operation result should be treated as unknown.