Skip to content

UCP via REST

Paths are relative to the rest endpoint in the manifest.

Endpoint/api/ucp/restMethodsGET · POST · PUTSpec version2026-04-08

REST binding

Paths are relative to the rest endpoint in the manifest.

POST /checkout-sessionsCreate
Prices the item and returns a new checkout session. 201 on creation; 200 when an idempotency key matched an existing one.
GET /checkout-sessions/{id}Retrieve
Reads the session back — its current status, totals, messages, and (once complete) the order.
PUT /checkout-sessions/{id}Update
Patches the buyer, the line item, or the codes, then re-prices. Fields you omit keep their current value.
POST /checkout-sessions/{id}/completeComplete
Re-checks availability and price, charges, and fulfils. Returns the session with order set.
POST /checkout-sessions/{id}/cancelCancel
Abandons an unfinished checkout. Idempotent.

Headers

Send UCP-Agent with your platform's profile URI on every request, and Idempotency-Key on every mutation. Request-Id is accepted for tracing. Authorization is optional — send a linked-identity bearer token when you have one.

create
curl -X POST \
  https://go.sessions.website/@<handle>/api/ucp/rest/checkout-sessions \
  -H 'Content-Type: application/json' \
  -H 'UCP-Agent: profile="https://you.example/ucp.json"' \
  -H 'Idempotency-Key: 6f1e…' \
  -d '{
    "line_items": [
      {"item": {"id": "gid://Sessions/ActivitySession/01J…"},
       "quantity": 1}
    ],
    "buyer": {"first_name": "Ada", "email": "ada@example.com"}
  }'

Paying

When the total is above zero, complete needs a credential in payment.instruments[]. Mark the instrument you want charged with selected: true; with a single instrument that is implied.

The token is a Stripe payment-method id created against the connected account the manifest advertises — initialise Stripe with the manifest's publishable_key and stripe_account, tokenize there, and send the resulting id. Sessions confirms it server-side on that same account.

Free checkouts need no credential
A zero-total checkout — a free class, a fully gift-card-covered purchase — completes with an empty body.
complete
curl -X POST \
  https://…/api/ucp/rest/checkout-sessions/{id}/complete \
  -H 'Content-Type: application/json' \
  -H 'UCP-Agent: profile="https://you.example/ucp.json"' \
  -H 'Idempotency-Key: 9c02…' \
  -d '{
    "payment": {
      "instruments": [{
        "handler_id": "stripe",
        "selected": true,
        "credential": {
          "type": "PAYMENT_GATEWAY",
          "token": "pm_1N…"
        }
      }]
    }
  }'

Status codes

A non-2xx is a protocol error with {code, content}; a 200 carrying messages is a business outcome.

200
The operation ran. Read status and messages for what happened.
201
A checkout session was created.
400
Malformed request: no line item, more than one, quantity above 1, or a body that is not a JSON object.
404
No such checkout session, no such route, or no such business.
405
That method is not offered on that path. The Allow header names the ones that are.
409
The session can no longer be changed — completed, cancelled, mid-completion, or its quote expired.
429
Rate limited. Back off for the interval in Retry-After.

The message codes a 200 can carry are the same across both bindings. See the protocol summary

Next