Payments API
Offline and Stripe card payments against the app's order rows. The server computes every amount.
On this page
Base URL: your app's origin ($APP_ORIGIN): the published host, a custom domain, or the platform origin for the builder preview. Errors answer { ok: false, error: { code, message } } unless noted. Add x-appbricx-env: dev or prod to pick the database explicitly; otherwise the host decides (preview means dev, a published host means prod).
Authentication
- App key + data marker
- A project API key (dpk_c_… in browsers, bound to the app's origins; dpk_s_… on servers) or the builder preview token, plus the data-API marker header. With an app session (the header, or the appbricx_app_session cookie) the call acts as that user under row-level security; without one it acts as a guest. A server key may assert x-appbricx-app-user, x-appbricx-app-role and x-appbricx-app-org.
Authorization: Bearer $APP_KEYx-appbricx-data-api: 1x-appbricx-app-session: $APP_SESSION (optional: acts as that user)
Endpoints
Confirm a card payment
POST/__appbricx/pay/confirm
After Stripe: ask Stripe about the order's open card payment and record paid, failed or processing.
- Auth
- App key + data marker:
Authorization: Bearer $APP_KEYx-appbricx-data-api: 1x-appbricx-app-session: $APP_SESSION (optional: acts as that user)
Body
| Name | Type | Description |
|---|---|---|
tablerequired | string | The order entity. |
idrequired | string | The order id. |
Response
{
"ok": true,
"status": "paid"
}Errors
| Status | Code | When |
|---|---|---|
| 401 | UNAUTHORIZED | Missing or invalid Authorization bearer ("Missing Authorization: Bearer <token>", "Invalid API key"). |
| 400 | PARAMS_INVALID | The x-appbricx-data-api: 1 header is missing. |
| 403 | ORIGIN_NOT_ALLOWED | A browser key used from an origin it isn't bound to (ORIGIN_REQUIRED when there is no Origin at all). |
| 429 | RATE_LIMITED | The project's per-minute request budget is spent (600 for preview tokens and browser keys, 1200 for server keys by default). |
| 404 | ORDER_NOT_FOUND | Can't read the order. |
| 404 | NO_CARD_PAYMENT | No card payment started. |
| 503 | STRIPE_NOT_CONNECTED | No Stripe key. |
| 502 | STRIPE_ERROR | Stripe failed. |
| 409 | PAYMENT_MISMATCH | The session belongs to another order or project. |
curl -X POST "$APP_ORIGIN/__appbricx/pay/confirm" \
-H "Authorization: Bearer $APP_KEY" \
-H "x-appbricx-data-api: 1" \
-H "x-appbricx-app-session: $APP_SESSION" \
-H "content-type: application/json" \
-d '{"table":"orders","id":"8c1d…"}'const res = await fetch(`${APP_ORIGIN}/__appbricx/pay/confirm`, {
method: "POST",
headers: {
Authorization: `Bearer ${APP_KEY}`,
"x-appbricx-data-api": "1",
"x-appbricx-app-session": APP_SESSION,
"content-type": "application/json",
},
body: JSON.stringify({
"table": "orders",
"id": "8c1d…"
}),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error?.message ?? data.error ?? res.statusText);Source: services/api/src/app-runtime/http/payments-routes.ts:126
Payment methods
GET/__appbricx/pay/methods
What the app accepts: offline always, card once Stripe is connected.
- Auth
- App key + data marker:
Authorization: Bearer $APP_KEYx-appbricx-data-api: 1x-appbricx-app-session: $APP_SESSION (optional: acts as that user)
Response
{
"ok": true,
"currency": "usd",
"methods": [
"offline",
"card"
]
}Errors
| Status | Code | When |
|---|---|---|
| 401 | UNAUTHORIZED | Missing or invalid Authorization bearer ("Missing Authorization: Bearer <token>", "Invalid API key"). |
| 400 | PARAMS_INVALID | The x-appbricx-data-api: 1 header is missing. |
| 403 | ORIGIN_NOT_ALLOWED | A browser key used from an origin it isn't bound to (ORIGIN_REQUIRED when there is no Origin at all). |
| 429 | RATE_LIMITED | The project's per-minute request budget is spent (600 for preview tokens and browser keys, 1200 for server keys by default). |
curl "$APP_ORIGIN/__appbricx/pay/methods" \
-H "Authorization: Bearer $APP_KEY" \
-H "x-appbricx-data-api: 1" \
-H "x-appbricx-app-session: $APP_SESSION"const res = await fetch(`${APP_ORIGIN}/__appbricx/pay/methods`, {
headers: {
Authorization: `Bearer ${APP_KEY}`,
"x-appbricx-data-api": "1",
"x-appbricx-app-session": APP_SESSION,
},
});
const data = await res.json();
if (!res.ok) throw new Error(data.error?.message ?? data.error ?? res.statusText);Source: services/api/src/app-runtime/http/payments-routes.ts:169
Latest payment of an order
GET/__appbricx/pay/for/:table/:id
The order's latest ledger entry, or null.
- Auth
- App key + data marker:
Authorization: Bearer $APP_KEYx-appbricx-data-api: 1x-appbricx-app-session: $APP_SESSION (optional: acts as that user)
Path parameters
| Name | Type | Description |
|---|---|---|
:tablerequired | string | The order entity. |
:idrequired | string | The order id. |
Response
{
"ok": true,
"payment": {
"method": "card",
"provider": "stripe",
"status": "paid",
"amount_cents": 4250,
"currency": "usd",
"created_at": "…"
}
}Errors
| Status | Code | When |
|---|---|---|
| 401 | UNAUTHORIZED | Missing or invalid Authorization bearer ("Missing Authorization: Bearer <token>", "Invalid API key"). |
| 400 | PARAMS_INVALID | The x-appbricx-data-api: 1 header is missing. |
| 403 | ORIGIN_NOT_ALLOWED | A browser key used from an origin it isn't bound to (ORIGIN_REQUIRED when there is no Origin at all). |
| 429 | RATE_LIMITED | The project's per-minute request budget is spent (600 for preview tokens and browser keys, 1200 for server keys by default). |
| 400 | BAD_TABLE | Invalid table name. |
| 404 | ORDER_NOT_FOUND | Can't read the order. |
curl "$APP_ORIGIN/__appbricx/pay/for/orders/8c1d…" \
-H "Authorization: Bearer $APP_KEY" \
-H "x-appbricx-data-api: 1" \
-H "x-appbricx-app-session: $APP_SESSION"const res = await fetch(`${APP_ORIGIN}/__appbricx/pay/for/orders/8c1d…`, {
headers: {
Authorization: `Bearer ${APP_KEY}`,
"x-appbricx-data-api": "1",
"x-appbricx-app-session": APP_SESSION,
},
});
const data = await res.json();
if (!res.ok) throw new Error(data.error?.message ?? data.error ?? res.statusText);Source: services/api/src/app-runtime/http/payments-routes.ts:177
Check out an order
POST/__appbricx/pay/checkout
Record payment for an order the caller can read. The total is Σ qty × catalog price over the order's line rows, computed on the server. card creates a Stripe Checkout session and returns its url.
- Auth
- App key + data marker:
Authorization: Bearer $APP_KEYx-appbricx-data-api: 1x-appbricx-app-session: $APP_SESSION (optional: acts as that user)
Body
| Name | Type | Description |
|---|---|---|
tablerequired | string | The contract's order entity. |
idrequired | string | The order id. |
methodoptional | "offline" | "card" | Default offline. |
returnUrloptional | string | card only: a URL on one of the app's hosts to come back to. |
Response
offline: { ok, method: "offline", status: "due", amountCents }. Card that can't start (no return URL, under 50 cents, Stripe not connected or failing): recorded offline with fallback: true and a note.
{
"ok": true,
"method": "card",
"status": "processing",
"amountCents": 4250,
"url": "https://checkout.stripe.com/c/pay/cs_…"
}Errors
| Status | Code | When |
|---|---|---|
| 401 | UNAUTHORIZED | Missing or invalid Authorization bearer ("Missing Authorization: Bearer <token>", "Invalid API key"). |
| 400 | PARAMS_INVALID | The x-appbricx-data-api: 1 header is missing. |
| 403 | ORIGIN_NOT_ALLOWED | A browser key used from an origin it isn't bound to (ORIGIN_REQUIRED when there is no Origin at all). |
| 429 | RATE_LIMITED | The project's per-minute request budget is spent (600 for preview tokens and browser keys, 1200 for server keys by default). |
| 400 | BAD_REQUEST | table or id missing. |
| 400 | NOT_AN_ORDER | Not the basket's order entity. |
| 404 | ORDER_NOT_FOUND | The caller can't read the order. |
| 400 | BAD_CONTRACT | The basket names an invalid column. |
curl -X POST "$APP_ORIGIN/__appbricx/pay/checkout" \
-H "Authorization: Bearer $APP_KEY" \
-H "x-appbricx-data-api: 1" \
-H "x-appbricx-app-session: $APP_SESSION" \
-H "content-type: application/json" \
-d '{"table":"orders","id":"8c1d…","method":"card","returnUrl":"https://tablefor.apps.appbricx.com/orders/8c1d"}'const res = await fetch(`${APP_ORIGIN}/__appbricx/pay/checkout`, {
method: "POST",
headers: {
Authorization: `Bearer ${APP_KEY}`,
"x-appbricx-data-api": "1",
"x-appbricx-app-session": APP_SESSION,
"content-type": "application/json",
},
body: JSON.stringify({
"table": "orders",
"id": "8c1d…",
"method": "card",
"returnUrl": "https://tablefor.apps.appbricx.com/orders/8c1d"
}),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error?.message ?? data.error ?? res.statusText);Source: services/api/src/app-runtime/http/payments-routes.ts:210