Endpoints a storefront calls with a public token: the store document, localized content, orders and invoices by id, slugs, forms, published web pages, promo, locale and setup. Read-only, safe to call from a browser.
The payment methods a checkout may offer (.dev/plans/invoice-providers.md G6). With a catalog (setup/payments.methods) - its enabled rows that serve the country, currency and total, a module row only while its module is installed, enabled and verified. Without one - the store's legacy Stripe services, unnamed. Send the chosen row's id as payment_method to process/order/make or process/payment/init. A module token is refused (403 module_token_forbidden).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
store | string | optional | Preferred in header, but store ID can be also used in request body. |
country | string | optional | The order's ISO-2 country (its price origin). |
currency | string | optional | ISO 4217 currency of the order. |
total | number | optional | The order total in major units (checked against a row's min / max). |
locale | string | optional | The label locale (xx_YY). |
Response
object — {methods: [{id, service, method, name, kind}]} - kind (card | bank | wallet | bnpl | other) only on a module gateway's method, as its module declares it.
Sample request
{
"country": "CZ",
"currency": "CZK",
"total": 1200,
"locale": "cs_CZ"
}Only read operations are allowed. Safe to use on frontend.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
store | string | optional | Preferred in header, but store ID can be also used in request body. |
mask | list | optional | Masks fields in response. Returns just subset of stored object. |
Response
StoreEntity — Returns store setup.
Sample request
{
"mask": [
"name",
"locales",
"status"
]
}Internally uses read/list/batch operations of /store/{storeId}/data content.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
store | string | optional | Preferred in header, but store ID can be also used in request body. |
name | string | optional | Collection name where to look up. Required unless slug is provided. |
slug | string | optional | Store slug locating the content instead of name. A document slug returns that document (query params ignored); a collection slug (a collection's setup/data slug or alias, resolved at request time - not a registry entry) lists the collection (id, query, limit, order_by, offset apply). For a collection with routing enabled the two-segment form {segment}/{slug} resolves that collection's document, and {segment}/{category}/{slug} a document filed under one of its categories. A REDIRECT slug has no content - it answers 404 here; read its target from /public/slug. Takes precedence over name. |
slug_locale | string | optional | Locale for slug resolution - rewrites the slug target into this locale. Defaults to the slug's own locale. With slug, the plain locale param is ignored. |
id | string | list | optional | Specific object ID or list of IDs. When not null, query params are ignored. |
locale | string | optional | Content is typically localized. Required with name (400 when missing/invalid; a single path segment such as en_US or default) - for slug requests use slug_locale instead. |
query | object | optional | Set of conditions to filter out documents. A scalar value ({"top" - true, "category" - "soup"}) is an equality shorthand; an object ({"price" - {"<=" - 100}}) or a list of such objects applies Firestore operators. |
offset | string | optional | ID of last document. |
limit | integer | optional | Maximum number of documents per page. |
order_by | object | optional | Field name and direction - [asc, desc]. When omitted, a collection with manual ordering enabled (setup/data reorder + order) is returned in that manual order (offset/limit paging applies to the ordered list); an explicit order_by always wins. |
mask | list | optional | Masks fields in response. Returns just subset of stored object. |
Response
object — Returns object or list of objects for given content.
Sample request
{
"name": "products",
"locale": "en_US",
"limit": 12
}Lists the products collection in en_US. Pass id (one id or a list) to read specific documents instead, or slug to resolve content by its public URL slug.
Internally uses /read route.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
store | string | optional | Preferred in header, but store ID can be also used in request body. |
id | string | required | Internal order ID. |
mask | list | optional | Masks fields in response. Returns just subset of stored object. |
Response
OrderEntity — Returns order object. Some order data is restricted under identity-token.
Sample request
{
"id": "ord_123"
}List a customer's orders. Identity-token callers are hard-scoped to their own customer (the uid param is ignored); access-token callers pass the uid to list. Used by the incore credits shop.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
store | string | optional | Preferred in header, but store ID can be also used in request body. |
uid | string | optional | Customer id to list orders for. Required for access-token callers; ignored (forced to the identity's customer) for identity-token callers. |
query | object | optional | Extra field filters merged on top of the customer scope. |
order_by | object | optional | Sort specification (field to asc/desc). |
limit | integer | optional | Max number of orders to return. |
offset | string | optional | Pagination cursor. |
mask | list | optional | Masks fields in each returned order. |
Response
list — Returns a list of the customer's OrderEntity objects.
Sample request
{
"uid": "user_123",
"limit": 20
}Identity-token callers omit uid - they always get their own orders.
Returns invoice data. Without style returns structured JSON; with a render style returns raw HTML (Content-Type text/html, invoice number in the X-Invoice-Number header). style=email sends the invoice email instead. A MODULE-issued invoice (its doc carries provider, .dev/plans/invoice-providers.md A4.1) is answered from the provider's document, never the platform template: JSON = the doc + provider (no app_url) + label/status/paid_on, payment = the provider's; html/web/custom = a hand-off page (200, meta refresh + link to provider.url, header X-Invoice-Url, <meta name=x-invoice-url>); pdf = application/pdf (the stored copy, else fetched once through the module's invoice.pdf and stored at store/{sid}/invoices/{number}.pdf), falling back to the hand-off; neither a URL nor a PDF = 404 invoice_document_unavailable; email = the module's invoice.send when the doc's provider.delivery is provider (501 invoice_send_unsupported), else the platform mail with invoice_url. The invoice doc is read only for a store whose setup/invoice.provider_history is non-empty.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
store | string | optional | Preferred in header, but store ID can be also used in request body. |
id | string | required | Internal order ID. |
style | string | optional | Render style - the template record id (html | pdf | web | any custom id; a store record at data/{locale}/templates/{style} overrides the bundled default of the same name); email sends the invoice email instead. Omitted returns invoice JSON. The legacy name 'template' is accepted as an alias. |
num | integer | optional | Index into the order's invoices array (an order can be invoiced multiple times). Defaults to the last (newest) invoice; without it an order with no invoice yet answers its invoice snapshot. Given and out of range = 404 invoice_not_found. |
Response
Entity — Invoice JSON (no style; always carries oid - the order id, locale - the order's, issued_on - the document's issue date YYYY-MM-DD, and paid_on when paid), raw HTML (html/pdf/web) - or, for a module-issued invoice, the hand-off page or the PDF - or send status (email). An order paid by transfer whose vendor (setup/organization) carries a bank_account adds a payment block - account, iban, vs (from the invoice number unless order.payment.vs), amount, currency, due (order.payment.due or issue date + setup/invoice.due_days, default 14) and the spayd QR Platba payload; rendered templates get it flattened as payment_* plus payment_qr (inline SVG data URI) and payment_due_date.
Sample request
{
"id": "ord_123",
"style": "html"
}Omit style for the invoice as JSON; html / pdf return the rendered document, email sends it.
Returns an order's proforma (.dev/plans/proforma-invoices.md) - the advance document of a bank-transfer order, resolved strictly through the unguessable order id. Without style - JSON {number, status (issued | paid | cancelled), issued_on, paid_on, url (a module's public document), order, currency, total, items, customer, vendor, payment {amount, currency, iban, account, vs, due, iban_print, spayd}}. With a style - raw HTML: a store record data/{locale}/templates/proforma overrides the bundled default; a module-issued proforma with a public document and no store record answers a hand-off page to it. 404 proforma_not_found.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
store | string | required | Store ID (header or body). |
id | string | required | The order id. |
style | string | optional | Render style (html | pdf | web | a custom id). Omitted returns JSON. |
locale | string | optional | Template locale (default the store's). |
Response
object — Proforma JSON, or raw HTML (header X-Invoice-Number).
Sample request
{
"id": "aBcDeF123"
}Internally uses /slug route. All slugs should reference to public content. A slug may target a single document (returns the document), a whole data collection (returns listing metadata - use /public/content with slug to fetch the documents), or a REDIRECT (the entry carries a "redirect" target instead of content - see the success description).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
store | string | optional | Preferred in header, but store ID can be also used in request body. |
slug | string | required | the slug - one path segment (same restrictions as an ID), {segment}/{slug} for a document of a collection with routing enabled (setup/data collections[].route), or {segment}/{category}/{slug} for a document filed under one of its route.categories (seo.category); {segment}/{category} alone serves the category's index page when its registry holds no such document. A segment ALIAS of the collection or of a category answers a redirect to the same path with the primary segments. A collection's own slug/alias resolves to the collection listing metadata (derived from setup/data - the slug registry holds documents only). Four or more segments are a 404. |
locale | string | optional | overrides locale of slug - typically in xx_XX format. Returns content for given slug but in overridden locale. |
mask | list | optional | Masks fields in response. Returns just subset of stored object. |
Response
object — The target document, or for collection slugs the metadata {id, ref, locale, count, name, template} with count being a live document count. A redirect entry answers {id, kind - "redirect", redirect, external, temporary?} instead - "redirect" is an absolute URL or a root-absolute path on the store site, "external" tells the two apart, and the store servers send it as a 301 (a 302 when "temporary" is true). Redirects win over a stored path. A FORMER slug of a document (a renamed one, kept by the content sync) answers the same redirect shape, pointing at the document's current URL. The registry is one document per URL key with a per-locale map - a locale-neutral redirect wins, then the requested locale's redirect or page, then the same language's other locales, then the store default and every other locale (a page before a foreign redirect).
Sample request
{
"slug": "about-us"
}Resolves the document behind /about-us. For a routed collection use the two-segment form (recipes/tomato-soup); a collection's own slug returns its listing metadata.
Stage ONE file for a later form submission (multipart/form-data: a binary file part plus the text fields). The same gates as /public/form - the form must be active (404), the form doc's origins (401), require_source (400) and captcha (403 captcha_required / captcha_failed; the token rides as the multipart text field captcha and must be a fresh one - tokens are single-use - the ticket carries no stamp) apply. With source the key must be an image/file/files variable of the placing document's contract and the file must pass its accept list and max_size (400 "File type not accepted" / 413 "File too large"); without source the platform caps alone apply - 10 MiB per file, images / PDF / plain text / Office documents only (never SVG, HTML, scripts or archives). The object is stored PRIVATE under store/{sid}/forms/{form}/_files/ (no public URL) with a staging ticket that expires after 24 h unless a submission claims it - put the answered {upload} under key in the submission's data within that window. Callers SHOULD proxy this leg through their own server with the same anti-bot guards as the submission (drop-core-server serves it as POST /form/{locale}/{form}/upload).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
store | string | optional | Preferred in header (multipart bodies carry it as a text field otherwise). |
form | string | required | Active form id (slug). |
locale | string | required | Locale of the submitting site (xx_YY or default) - selects the source document read. |
key | string | required | The file-kind variable key the file is uploaded for. The submission must reference the ticket under the same key. |
file | file | required | The binary file part (multipart/form-data field named file). |
name | string | optional | File name to store (defaults to the part's filename). |
content_type | string | optional | MIME type to store (defaults to the part's). Must be in the platform list and the variable's accept. |
source | string | optional | The placing document ({collection}/{docId}) - validates key against its contract. |
origin | string | optional | Browser origin relayed by a trusted proxy (consulted only when the form restricts origins). |
Response
object — Returns {upload, name, size, content_type} - upload is the ticket id the submission claims as {upload} under key.
Sample request
{
"form": "contact",
"locale": "en_US",
"key": "cv"
}Multipart only - send a binary file part with these text fields. The Try-it rail cannot attach a file; use the render server's POST /form/{locale}/{form}/upload from a page.
Returns promo data for given id (customer).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
store | string | optional | Preferred in header, but store ID can be also used in request body. |
id | string | required | actual ID of promo - typically customer id. |
mask | list | optional | filters response - credits | coupons | referrals |
Sample request
{
"id": "user_123",
"mask": [
"credits"
]
}Returns global locale reference data for an ISO country code, read from the Realtime DB. Flat-merges the country (currency / unit / symbol / region / name) and vat (vat rate / reduced rates) nodes into one object; the merged country field carries the ISO code itself. Store-independent, but a valid store + access token is still required.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
store | string | optional | Preferred in header, but store ID can be also used in request body. Required for auth even though the data is global. |
code | string | required | ISO country code, e.g. "CZ" (case-insensitive). |
mask | list | optional | Masks fields in response. Returns just subset of merged fields (e.g. country, vat, currency, unit, symbol). |
Response
object — Flat-merged locale object — country reference data plus VAT.
Sample request
{
"code": "DE",
"mask": [
"country",
"currency",
"vat"
]
}Read a single store setup document (store/{sid}/setup/{name}) that has opted into public visibility with public: true on the doc itself. Any other case - missing doc, doc without the flag, malformed name - answers the SAME generic 400, so the endpoint does not reveal which setup docs exist. Intended for browser-safe config a storefront client needs at runtime - e.g. the credits shop reads setup/payments (the Stripe publishable key).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
store | string | optional | Preferred in header, but store ID can be also used in request body. |
name | string | required | Setup document name (e.g. payments). Single path segment. |
mask | list | optional | Masks fields in response - returns just the listed top-level fields. |
Response
object — The setup document body (optionally masked). Generic 400 for anything not explicitly public.
Sample request
{
"name": "payments"
}Custom-module STOREFRONT leg (.dev/plans/custom-modules.md D9 / 5.5) - the core half of the reserved /m/{module}/** path space every store origin carries. The tenant server (drop-core-server) forwards such a hit here on the store's own serving token, which already grants public, so no token is re-granted for a module; the Studio renderer's preview bridge uses the same route. The module's web point is called through the gateway with the install's signed envelope and its non-secret config, and its answer is relayed - status, content-type, cache-control, body - so a module can serve HTML, JSON or a redirect under the store's own domain. The visitor's identity travels as the request's identity-token header or a relayed identity token in the body, resolved to identity = {customer} on the envelope; an invalid one is 401. The module's 5xx or a transport failure answers 502 module_unavailable; a module 4xx is relayed verbatim. A module that is not installed, is disabled, or does not declare routes.web answers 404. One module_web stat row per hit.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
store | string | optional | Preferred in header, but store ID can be also used in request body. |
module | string | required | The installed module id (the manifest id, not the catalog key). |
path | string | optional | The sub-path inside the module's own space, leading slash, no query or fragment. Defaults to /. |
method | string | optional | GET (default) | POST | PUT | DELETE. |
query | object | optional | Flat query map. Repeated keys arrive as the first value. |
body | object | optional | The request body for a non-GET call, max 256 KiB at the caller. |
locale | string | optional | The visitor's locale (xx_YY), from the store's locale cookie at the tenant server. |
identity | string | optional | A relayed identity token when the caller cannot send the identity-token header. |
guard | string | optional | passed - the caller vouches its form guard (honeypot, signed timing, rate limit) ran on this request. A path listed in the manifest's routes.guarded reaches the module ONLY with it; without it the answer is the envelope {status - 428, body - {error - guard_required}} and the module is not called (the tenant server then runs its FormGuard chain and retries, or - on a GET - answers the guard fields). |
Response
object — {status, headers = {content-type, cache-control?}, body, guarded?} - the module's answer, for the caller to re-emit; guarded lists the module's guarded paths (when it has any) so the caller can guard before forwarding.
Sample request
{
"module": "echo",
"path": "/ping"
}Store-service STOREFRONT leg on the core path (.dev/plans/modules/services.md D9) - a /fn/{service}/** call that no sandbox host runs: the Studio / document-editor preview, forward-only render servers (own servers, server-web-prod) and custom front ends. The core runs NO guest code: it resolves the service doc, the published version, the declared secrets and the store's serving token (re-read from custody on every call; a store without one is provisioned once, else 409 no_serving_token) and forwards to the shared service-runner, whose answer is relayed in a 200 envelope - status, content-type / cache-control / location (default cache-control no-store), body as text - like /public/module. The relayed guard: passed, ip, origin and referer are taken only from a trusted relay - the store's serving token, master, owner / editor, or a token with an explicit path scope; from any other caller (an unscoped service token, an identity-token request) they are ignored. A route marked guarded needs a trusted guard: passed (else the envelope {status 428, body {error guard_required}} without calling the code); every envelope of a service with guarded routes lists them in guarded. Route access (.dev/plans/modules/service-access.md), decided before the code runs: a private route answers 404 (the no-route answer) unless a trusted relay calls with host other than site; a site route is judged on Sec-Fetch-Site / Origin vs the addressed host - the relayed fetch_site / origin / site_host from a trusted relay, else the caller's own request to the core - and a foreign, unlisted origin is the envelope {status 403, body {error origin_not_allowed}}; a signed-in route without a visitor identity is the envelope {status 401, body {error identity_required}}. Refusals count as refused in the route health, never as a log line. A trusted relay's envelopes list the non-public route keys in restricted (route key to level, e.g. GET /config - site). The visitor's identity (the identity-token header or a relayed identity) reaches the code's drop.api only on an identity: true (or signed-in) route. 404 service_unavailable for a plan without the services feature, an unknown / disabled / unpublished service or no matching route. The token's path scope must cover store/{sid}/services/{id}. Writes one log line (host core, or studio) + the route health, and one service_call stat row.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
store | string | optional | Preferred in header, but store ID can be also used in request body. |
service | string | required | The service id (/fn/{id}/...). |
path | string | optional | The path after /fn/{id}, leading slash, no query or fragment. Defaults to /. |
method | string | optional | GET (default) | POST | PUT | DELETE. |
query | object | optional | Flat query map. Repeated keys arrive as the first value. |
body | object | optional | JSON request body, at most 256 KiB (413 body_too_large). |
locale | string | optional | The visitor's locale (xx_YY). |
identity | string | optional | A relayed identity token when the caller cannot send the identity-token header. |
guard | string | optional | passed - the caller's form guard ran on this request (required by a guarded route). |
host | string | optional | site - a render server relaying a visitor's request (judged by route access); studio marks a console preview (its log lines say host studio; a trusted relay's studio call skips the site check and may run private routes); otherwise core. |
fetch_site | string | optional | The visitor's raw Sec-Fetch-Site header, relayed by a render server (trusted relay only). |
site_host | string | optional | The host the visitor addressed (x-forwarded-host or host), relayed by a render server (trusted relay only). |
Response
object — {status, headers = {content-type?, cache-control?, location?}, body, guarded?, restricted?, error?} - the service's answer for the caller to re-emit (403 origin_not_allowed / 401 identity_required access refusals ride the envelope too).
Errors
404 service_unavailable; 409 no_serving_token; 401 invalid identity; 413 body_too_large.
Sample request
{
"service": "echo",
"path": "/ping"
}A store service's durable key-value state (.dev/plans/modules/services.md D12, services/{id}/state/{key}) - the binding the service hosts use on the serving token; the HOST names the service, never the guest code (drop.api cannot reach /api/public/service*). Keys 1-64 of A-Z a-z 0-9 _ - (no leading _); a value is at most 64 KiB of JSON (413 value_too_large); set with a null / absent value deletes the key. set is checked as a WRITE against the token's path scope (every other /public call is a read) and needs the tier feature services (403 tier_required). 404 service_unavailable for an unknown service. Only the store's serving token (the service hosts) and master reach it - any other token, and any identity-token request, is 403 serving_token_required.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
store | string | optional | Preferred in header, but store ID can be also used in request body. |
service | string | required | The service id. |
op | string | required | get | set. |
key | string | required | The key. |
value | object | optional | The JSON value to store (set). |
Response
object — get -> {value} (null when absent); set -> {ok: true}
Sample request
{
"service": "echo",
"op": "get",
"key": "counter"
}The delivery methods a cart may choose (plans/carriers 3.6) - setup/delivery priced for the cart - enabled, shipping to country (a method without countries ships to the sender's country only), free_from applied on total, the per-origin price when set, minus the methods of a module:{id} carrier that is not selectable (disabled / unverified / uninstalled). The storefront server's POST /delivery/:locale and the Studio bridge return this list.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
store | string | optional | Preferred in header, but store ID can be also used in request body. |
country | string | optional | Destination ISO-2 country. |
total | number | optional | The cart total (the free_from threshold). |
origin | string | optional | The price origin (country). |
locale | string | optional | The label locale (xx_YY). |
Response
object — {methods: [{id, carrier, service, kind, name, price, currency, vat, free, cod, point_types, widget}]}
Sample request
{
"country": "CZ",
"total": 1200,
"locale": "cs_CZ"
}Pickup points for the checkout (plans/carriers 3.4) - only for a carrier some enabled point / box method of the store names (else 404 carrier_not_offered); cached per instance ~10 min per (store, carrier, query).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
store | string | optional | Preferred in header, but store ID can be also used in request body. |
carrier | string | required | The carrier tag of a delivery method. |
country | string | optional | ISO-2 country. |
type | string | optional | The carrier point type (e.g. AlzaBox). |
q | string | optional | Free-text search (name, town, street, zip). |
locale | string | optional | The label locale (xx_YY). |
Response
object — {points: [...]}
Sample request
{
"carrier": "mock",
"country": "CZ"
}The customer tracking view (plans/carriers 3.6) - order + tracking (the tracking number is the proof; a wrong one is 404). Answers {order, status, carrier, tracking, tracking_url, last, town, history - [{code, status, text, at}]}; no PII beyond the destination town.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
store | string | optional | Preferred in header, but store ID can be also used in request body. |
order | string | required | The order id. |
tracking | string | required | The shipment's tracking number. |
Response
object — {order, status, carrier, tracking, tracking_url, last, town, history}
Sample request
{
"order": "Hk8yR64vJf2bz33yc44B",
"tracking": "MOCK1234"
}