Pingerchips LogoPingerchips
Durable ObjectsReference

HTTP API

REST endpoints for reading and writing Durable Objects from any language.

Every Durable Object operation is available over REST — useful for server-to-server calls, scripts, and languages without an SDK.

Base path:

/api/v1/objects/{app_id}/{type}/{key}

{app_id} accepts either your App Key or your App ID. {type} and {key} are arbitrary non-empty strings.

The pingerchips-js-server SDK wraps all of this — see the Server SDK. Use the raw API only when you have no SDK.


Authentication

Every request carries two headers — see Authentication.

HeaderValue
X-App-KeyApp Key
X-App-SecretApp Secret

No request signing, no timestamp. The {app_id} path segment must be the App Key or App ID of the authenticated app. Failure → 401 { "errors": [{ "status": "401", "title": "Unauthorized" }] }.

curl -X PUT https://queue.pingerchips.com/api/v1/objects/$APP_KEY/order/order-42/status \
  -H "X-App-Key: $APP_KEY" \
  -H "X-App-Secret: $APP_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"value":"shipped"}'

Endpoints

Read full state

GET /api/v1/objects/{app_id}/{type}/{key}
{
  "state": {
    "status": "processing",
    "assigned_to": "agent-7",
    "retry_count": 2
  },
  "log_id": 17
}

A never-written object returns { "state": {}, "log_id": 0 }.


Read one slot

GET /api/v1/objects/{app_id}/{type}/{key}/{slot}
{ "value": "processing" }

Returns { "value": null } if the slot is unset.


Set one slot

PUT /api/v1/objects/{app_id}/{type}/{key}/{slot}
Content-Type: application/json

{ "value": "shipped" }
{ "log_id": 18 }

Set multiple slots (atomic)

The body is a plain object — its keys are the slots. Broadcasts a single batch event.

PATCH /api/v1/objects/{app_id}/{type}/{key}
Content-Type: application/json

{
  "status": "shipped",
  "shipped_at": 1718884800000
}
{ "log_id": 19 }

Increment

POST /api/v1/objects/{app_id}/{type}/{key}/increment
Content-Type: application/json

{ "slot": "retry_count", "by": 1 }

by defaults to 1. An unset slot is treated as 0.

{ "log_id": 20, "value": 3 }

Append

Appends one item to the list stored at slot (initialised to [] if unset). The full updated list is stored.

POST /api/v1/objects/{app_id}/{type}/{key}/append
Content-Type: application/json

{
  "slot": "history",
  "value": { "event": "shipped", "at": 1718884800000 }
}
{ "log_id": 21 }

Delete a slot

DELETE /api/v1/objects/{app_id}/{type}/{key}/{slot}
{ "log_id": 22 }

Transaction

Atomic multi-write. The body is a bare JSON array of operations. All operations commit together in one log entry and broadcast a single batch event.

POST /api/v1/objects/{app_id}/{type}/{key}/transaction
Content-Type: application/json

[
  { "op": "set",       "key": "status",      "value": "shipped" },
  { "op": "increment", "key": "retry_count", "by": 1 },
  { "op": "append",    "key": "history",     "value": { "event": "shipped" } },
  { "op": "delete",    "key": "temp_lock" }
]

Valid op values: set, delete, increment, append. Each op names the slot with key.

{ "log_id": 23 }

The HTTP transaction is write-only — there is no get op, so it cannot express "only write if the current value is X". For conditional writes, use the Server SDK transaction(ops) under a read you performed first, or gate the call in your own code.


Replay the log

GET /api/v1/objects/{app_id}/{type}/{key}/log?after=17

Returns every log entry with log_id > after (default 0), oldest first. increment and append are materialised as set entries.

{
  "items": [
    { "op": "set", "key": "status", "value": "shipped", "log_id": 18 },
    { "op": "set", "key": "shipped_at", "value": 1718884800000, "log_id": 19 }
  ]
}

Purge

Permanently deletes all state and log entries for the object.

DELETE /api/v1/objects/{app_id}/{type}/{key}
204 No Content

Error responses

StatusBodyCause
401{"errors":[{"status":"401","title":"Unauthorized"}]}Missing / wrong X-App-Key / X-App-Secret, or the route app_id isn't the authenticated app
422{"error": "..."}Operation failed (e.g. bad transaction op)

Real-time

Every write broadcasts a change / batch event to subscribers of the object's channel. Subscribe from the browser with pingerchips.object(), or from another language over the durable:{appKey}:{type}:{key} channel directly.

On this page