Platform paths
A site reaches the rest of its workspace through paths under /_platform/. Its Worker calls them with plain fetch, on its own hostname or on https://digize.com, and Digize’s Outbound Worker answers them from the App Worker. The site never holds a key: Outbound knows which workspace and site is calling from Dispatch, and nothing the site sends can change that.
| Path | Takes | Answers |
|---|---|---|
GET /_platform/context | Nothing | The site's identity: workspaceId, siteId and hostname |
POST /_platform/forms | A form: JSON, urlencoded or multipart, up to 256 KB | { submissionId }, or a 303 for a plain HTML form |
POST /_platform/store/page-data | A page data query: home, product, collection or search | The store and that page's products, from the catalog |
POST /_platform/store/checkout | A cart and where to send the customer afterwards | { checkoutId, url }: Stripe Checkout's page |
POST /_platform/store/checkout-status | { checkoutId } | Whether it's open, completed or expired, and the order number |
POST /_platform/store/reviews | { productSlug?, limit?, cursor? } | The reviews widget's reviews, a page at a time |
POST /_platform/store/submit-review | A visitor's review, with a Turnstile token | { reviewId }; the review waits for the team |
Calling them
Section titled “Calling them”From a Worker, fetch the path on the request’s own origin:
export default { async fetch(request: Request): Promise<Response> { const site = await fetch(new URL("/_platform/context", request.url)); const { workspaceId, siteId, hostname } = (await site.json()) as { workspaceId: string; siteId: string; hostname: string; }; return Response.json({ workspaceId, siteId, hostname }); },};A browser can’t call them: a visitor’s request for /_platform/forms on the site’s hostname goes to the site’s Worker like any other path, and the Worker passes it on (as the quickstart does). The script Digize deploys with static sites does that for every platform path.
Every call is JSON in and JSON out, except a form, which can also be urlencoded or multipart. Each answer has cache-control: no-store.
Answers and errors
Section titled “Answers and errors”A call that works answers 200 with its value as the whole body, such as { "submissionId": "fs_01JF…" }. One that doesn’t answers with the error’s status and:
{ "error": { "code": "invalid", "message": "Enter an email address or a phone number.", "details": { "fields": { "email": "Enter an email address." } } }}code |
Status | |
|---|---|---|
invalid |
400 | What was sent isn’t valid. details.fields, when it’s there, names the fields. 405 for the wrong method, 415 for a form in another format. |
unauthorized |
401 | Only from https://digize.com/api/store/…, for a request without the site context. |
forbidden |
403 | Turnstile didn’t pass, or the site isn’t the workspace’s any more. |
not_found |
404 | No such product, collection or checkout, or no such path. |
conflict |
409 | The same checkout is still starting. |
too_large |
413 | The body is over the path’s limit. |
rate_limited |
429 | Over the path’s rate. |
unavailable |
503 | Digize couldn’t take the call just now; try again. |
message is written for people and may change; branch on code.
The site’s identity
Section titled “The site’s identity”GET /_platform/context answers who Outbound says is calling: workspaceId, siteId, and the hostname the visitor’s request came to. Under a route, that’s the routed Worker’s id on the other Worker’s hostname.
Calling the App Worker
Section titled “Calling the App Worker”Any other request a site makes to https://digize.com carries the site’s identity, signed by Outbound for 60 seconds, in x-digize-site-context, without the visitor’s cookies or authorization header. The App Worker answers the storefront’s calls there too, at POST https://digize.com/api/store/<call>, where <call> is page-data, checkout, checkout-status, reviews or submit-review. They take the same bodies as the paths under /_platform/store/.