HTTP API
Use the OpenAPI contract as the source of truth for routes, schemas, and stable error envelopes.
Call the deployed HTTP contract
HTTP API reference points to the running release's OpenAPI document and public routing conventions.
The deployed document is authoritative for exact routes and schemas, while the SDK handles common envelope and session details.
Use it for non-TypeScript clients, contract generation, gateway review, or SDK contract verification.
Requirements for HTTP API
- Prerequisite — A ready FFDB deployment and access to /openapi.json.
- Prerequisite — A generator or HTTP client that preserves tagged values, headers, and error envelopes.
- Required value — Base URL, project/credential context, Content-Type, request body, X-Request-Id response, and idempotency header where required.
- Required value — The OpenAPI document from the exact deployed release.
OpenAPI contract
A running deployment serves its current OpenAPI document at /openapi.json through the same compiled nginx gateway used by applications. In packaged Docker releases that gateway is the only host-published FFDB ingress and it proxies the request to Axum on the private Compose network. Prefer @ffdb/client for TypeScript applications because it normalizes tagged worker envelopes, token refresh, retries, storage provider calls, and lossless SQL values.
curl --fail http://127.0.0.1:5173/openapi.json > ffdb-openapi.jsonDirect HTTP example
Use the exact deployed origin and a route-appropriate credential. Preserve the response request ID, send parameters as typed JSON rather than interpolating SQL text, and bound result rows.
curl --fail-with-body --request POST --header "Authorization: Bearer $FFDB_USER_ACCESS_TOKEN" --header "Content-Type: application/json" --data '{"sql":"select id, title from documents where id = ?1","parameters":[{"type":"text","value":"doc_123"}],"options":{"max_rows":1}}' "$FFDB_URL/v1/projects/$FFDB_PROJECT_ID/query"Arguments, returns, and errors
Each generated operation entry below combines path-level and operation-level parameters, marks every value required or optional, names the credential scheme, summarizes the JSON request body, lists success and error responses, and identifies routes that require Idempotency-Key. The deployed /openapi.json remains authoritative for complete JSON Schema.
- developerBearer is an opaque platform session for instance and organization administration.
- projectBearer accepts the route-appropriate project developer key or end-user JWT.
- userBearer is a project end-user access token evaluated with project identity and RLS claims.
- Errors use the stable code/message/request_id/details envelope and include X-Request-Id.
HTTP: System
- GET /healthz — health; auth: public; arguments: none; body: none; returns: 200: object; errors: none declared
- GET /readyz — readiness; auth: public; arguments: none; body: none; returns: 200: object; 503: ErrorEnvelope; errors: 503
- GET /metrics — metrics; auth: public; arguments: none; body: none; returns: 200: string; 503: ErrorEnvelope; errors: 503
- GET /openapi.json — openapi; auth: public; arguments: none; body: none; returns: 200: object; errors: none declared
HTTP: Instance
- GET /v1/instance/setup/status — getPublicInstanceSetupStatus; auth: public; arguments: none; body: none; returns: 200: object; 503: ErrorEnvelope; errors: 503
- GET /v1/instance — getInstance; auth: developerBearer; arguments: none; body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- POST /v1/instance — completeOrReconfigureInstance; auth: developerBearer; arguments: Idempotency-Key (header, required, string); body: required object JSON; returns: 200: object; 400: ErrorEnvelope; 403: ErrorEnvelope; 409: ErrorEnvelope; errors: 400, 403, 409; Idempotency-Key required
- PATCH /v1/instance/organization-creation-policy — updateOrganizationCreationPolicy; auth: developerBearer; arguments: none; body: required object JSON; returns: 200: object; 403: ErrorEnvelope; errors: 403
- POST /v1/instance/billing/connect/onboarding — createInstanceConnectOnboarding; auth: developerBearer; arguments: Idempotency-Key (header, required, string); body: required object JSON; returns: 200: object; 403: ErrorEnvelope; 409: ErrorEnvelope; errors: 403, 409; Idempotency-Key required
- POST /v1/instance/billing/refresh — refreshInstanceBillingAccount; auth: developerBearer; arguments: none; body: none; returns: 200: object; 403: ErrorEnvelope; 409: ErrorEnvelope; errors: 403, 409
- GET /v1/instance/administrators — listInstanceAdministrators; auth: developerBearer; arguments: none; body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- POST /v1/instance/administrators — grantInstanceAdministrator; auth: developerBearer; arguments: none; body: required object JSON; returns: 200: object; 403: ErrorEnvelope; 409: ErrorEnvelope; errors: 403, 409
- DELETE /v1/instance/administrators/{user_id} — revokeInstanceAdministrator; auth: developerBearer; arguments: user_id (path, required, string); body: none; returns: 200: object; 403: ErrorEnvelope; 409: ErrorEnvelope; errors: 403, 409
- GET /v1/instance/organizations — listInstanceOrganizations; auth: developerBearer; arguments: none; body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- PATCH /v1/instance/organizations/{organization_id} — setInstanceOrganizationDisabled; auth: developerBearer; arguments: organization_id (path, required, string); body: required { disabled: boolean } JSON; returns: 200: object; 403: ErrorEnvelope; 409: ErrorEnvelope; errors: 403, 409
- GET /v1/instance/users — listInstanceUsers; auth: developerBearer; arguments: none; body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- PATCH /v1/instance/users/{user_id} — setInstanceUserDisabled; auth: developerBearer; arguments: user_id (path, required, string); body: required { disabled: boolean } JSON; returns: 200: object; 403: ErrorEnvelope; 409: ErrorEnvelope; errors: 403, 409
- GET /v1/instance/billing-exemptions — listInstanceBillingExemptions; auth: developerBearer; arguments: none; body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- PUT /v1/instance/billing-exemptions/{organization_id} — grantInstanceBillingExemption; auth: developerBearer; arguments: organization_id (path, required, string); body: required object JSON; returns: 200: object; 403: ErrorEnvelope; errors: 403
- DELETE /v1/instance/billing-exemptions/{organization_id} — revokeInstanceBillingExemption; auth: developerBearer; arguments: organization_id (path, required, string); body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- GET /v1/instance/plans — listInstancePlans; auth: developerBearer; arguments: none; body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- PUT /v1/instance/plans/{tier} — putInstancePlan; auth: developerBearer; arguments: tier (path, required, "free" | "pay_as_you_go" | "pro"); body: required object JSON; returns: 200: object; 400: ErrorEnvelope; 403: ErrorEnvelope; errors: 400, 403
- DELETE /v1/instance/plans/{tier} — retireInstancePlan; auth: developerBearer; arguments: tier (path, required, "free" | "pay_as_you_go" | "pro"); body: none; returns: 200: object; 403: ErrorEnvelope; 409: ErrorEnvelope; errors: 403, 409
HTTP: Developer auth
- POST /v1/developer/bootstrap — bootstrapDeveloper; auth: public; arguments: none; body: required object JSON; returns: 200: object; 409: ErrorEnvelope; errors: 409
- POST /v1/developer/sign-in — developerSignIn; auth: public; arguments: none; body: required object JSON; returns: 200: object; 401: ErrorEnvelope; errors: 401
- POST /v1/developer/refresh — developerRefresh; auth: public; arguments: none; body: required object JSON; returns: 200: object; 401: ErrorEnvelope; errors: 401
- POST /v1/developer/sign-out — developerSignOut; auth: public; arguments: none; body: required object JSON; returns: 200: object; 401: ErrorEnvelope; errors: 401
- POST /v1/developer/invitations/accept — acceptOrganizationInvitation; auth: public; arguments: none; body: required object JSON; returns: 200: object; 400: ErrorEnvelope; errors: 400
HTTP: Organizations
- GET /v1/organizations — listOrganizations; auth: developerBearer; arguments: none; body: none; returns: 200: object; 401: ErrorEnvelope; errors: 401
- POST /v1/organizations — createOrganization; auth: developerBearer; arguments: none; body: required object JSON; returns: 200: object; 400: ErrorEnvelope; errors: 400
- GET /v1/organizations/{organization_id}/projects — listProjects; auth: developerBearer; arguments: organization_id (path, required, string); body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- GET /v1/organizations/{organization_id}/members — listMembers; auth: developerBearer; arguments: organization_id (path, required, string); body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- POST /v1/organizations/{organization_id}/members — addMember; auth: developerBearer; arguments: organization_id (path, required, string); body: required object JSON; returns: 200: object; 409: ErrorEnvelope; errors: 409
- PATCH /v1/organizations/{organization_id}/members/{user_id} — updateMember; auth: developerBearer; arguments: organization_id (path, required, string); user_id (path, required, string); body: required object JSON; returns: 200: object; 409: ErrorEnvelope; errors: 409
- DELETE /v1/organizations/{organization_id}/members/{user_id} — removeMember; auth: developerBearer; arguments: organization_id (path, required, string); user_id (path, required, string); body: none; returns: 200: object; 409: ErrorEnvelope; errors: 409
- POST /v1/organizations/{organization_id}/invitations — inviteMember; auth: developerBearer; arguments: organization_id (path, required, string); body: required object JSON; returns: 200: object; 409: ErrorEnvelope; errors: 409
HTTP: Projects
- POST /v1/projects — createProject; auth: developerBearer; arguments: Idempotency-Key (header, required, string); body: required object JSON; returns: 200: object; 409: ErrorEnvelope; errors: 409; Idempotency-Key required
- GET /v1/projects/{project_id}/api-keys — listApiKeys; auth: developerBearer; arguments: project_id (path, required, string); body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- POST /v1/projects/{project_id}/api-keys — createApiKey; auth: developerBearer; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; 403: ErrorEnvelope; errors: 403
- POST /v1/projects/{project_id}/api-keys/{api_key_id}/revoke — revokeApiKey; auth: developerBearer; arguments: project_id (path, required, string); api_key_id (path, required, string); body: none; returns: 200: object; 404: ErrorEnvelope; errors: 404
- POST /v1/projects/{project_id}/keys/rotate — rotateSigningKey; auth: developerBearer; arguments: project_id (path, required, string); body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
HTTP: End-user auth
- POST /v1/projects/{project_id}/auth/register — registerUser; auth: public; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; 400: ErrorEnvelope; errors: 400
- POST /v1/projects/{project_id}/auth/verify — verifyEmail; auth: public; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; 400: ErrorEnvelope; errors: 400
- POST /v1/projects/{project_id}/auth/sign-in — userSignIn; auth: public; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; 401: ErrorEnvelope; errors: 401
- POST /v1/projects/{project_id}/auth/refresh — userRefresh; auth: public; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; 401: ErrorEnvelope; errors: 401
- POST /v1/projects/{project_id}/auth/sign-out — userSignOut; auth: public; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; 401: ErrorEnvelope; errors: 401
- POST /v1/projects/{project_id}/auth/password/reset — startPasswordReset; auth: public; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; errors: none declared
- POST /v1/projects/{project_id}/auth/password/reset/complete — completePasswordReset; auth: public; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; 400: ErrorEnvelope; errors: 400
- POST /v1/projects/{project_id}/auth/password/change — changePassword; auth: userBearer; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; 401: ErrorEnvelope; errors: 401
- GET /v1/projects/{project_id}/auth/sessions — listSessions; auth: userBearer; arguments: project_id (path, required, string); body: none; returns: 200: object; 401: ErrorEnvelope; errors: 401
- DELETE /v1/projects/{project_id}/auth/sessions/{session_id} — revokeSession; auth: userBearer; arguments: project_id (path, required, string); session_id (path, required, string); body: none; returns: 200: object; 404: ErrorEnvelope; errors: 404
- GET /v1/projects/{project_id}/auth/settings — getAuthSettings; auth: developerBearer; arguments: project_id (path, required, string); body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- PATCH /v1/projects/{project_id}/auth/settings — updateAuthSettings; auth: developerBearer; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; 400: ErrorEnvelope; errors: 400
- GET /v1/projects/{project_id}/auth/users — listAuthUsers; auth: developerBearer; arguments: project_id (path, required, string); body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- PATCH /v1/projects/{project_id}/auth/users/{user_id} — updateAuthUser; auth: developerBearer; arguments: project_id (path, required, string); user_id (path, required, string); body: required object JSON; returns: 200: object; 404: ErrorEnvelope; errors: 404
HTTP: Data
- POST /v1/projects/{project_id}/query — query; auth: projectBearer; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; 403: ErrorEnvelope; errors: 403
- POST /v1/projects/{project_id}/transaction — transaction; auth: projectBearer; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; 409: ErrorEnvelope; errors: 409
- GET /v1/projects/{project_id}/schema — schema; auth: developerBearer; arguments: project_id (path, required, string); body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- GET /v1/projects/{project_id}/policies — policies; auth: developerBearer; arguments: project_id (path, required, string); body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- GET /v1/projects/{project_id}/migrations — migrationHistory; auth: developerBearer; arguments: project_id (path, required, string); body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- POST /v1/projects/{project_id}/migrations — applyMigration; auth: developerBearer; arguments: project_id (path, required, string); Idempotency-Key (header, required, string); body: required object JSON; returns: 200: object; 409: ErrorEnvelope; errors: 409; Idempotency-Key required
- POST /v1/projects/{project_id}/migrations/{migration_id}/rollback — rollbackMigration; auth: developerBearer; arguments: project_id (path, required, string); migration_id (path, required, string); Idempotency-Key (header, required, string); body: none; returns: 200: object; 409: ErrorEnvelope; errors: 409; Idempotency-Key required
- POST /v1/projects/{project_id}/seed — seed; auth: developerBearer; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; 403: ErrorEnvelope; errors: 403
HTTP: Billing
- GET /v1/organizations/{organization_id}/billing — getOrganizationBilling; auth: developerBearer; arguments: organization_id (path, required, string); body: none; returns: 200: PlatformBillingSummary; 403: ErrorEnvelope; 503: ErrorEnvelope; errors: 403, 503
- POST /v1/organizations/{organization_id}/billing/checkout — createOrganizationBillingCheckout; auth: developerBearer; arguments: organization_id (path, required, string); Idempotency-Key (header, required, string); body: required CreatePlatformCheckoutRequest JSON; returns: 201: BillingRedirect; 400: ErrorEnvelope; 403: ErrorEnvelope; 409: ErrorEnvelope; 503: ErrorEnvelope; errors: 400, 403, 409, 503; Idempotency-Key required
- POST /v1/organizations/{organization_id}/billing/portal — createOrganizationBillingPortal; auth: developerBearer; arguments: organization_id (path, required, string); Idempotency-Key (header, required, string); body: none; returns: 201: BillingRedirect; 403: ErrorEnvelope; 409: ErrorEnvelope; 503: ErrorEnvelope; errors: 403, 409, 503; Idempotency-Key required
- GET /v1/organizations/{organization_id}/billing/invoices — listOrganizationBillingInvoices; auth: developerBearer; arguments: organization_id (path, required, string); body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- GET /v1/organizations/{organization_id}/billing/usage — getOrganizationBillingUsage; auth: developerBearer; arguments: organization_id (path, required, string); body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- POST /v1/billing/webhooks/stripe — receiveStripeBillingWebhook; auth: public; arguments: Stripe-Signature (header, required, string); body: required object JSON; returns: 200: { received: boolean; duplicate?: boolean }; 400: ErrorEnvelope; 409: ErrorEnvelope; 503: ErrorEnvelope; errors: 400, 409, 503
HTTP: Commerce
- GET /v1/projects/{project_id}/payments — getProjectPaymentsSummary; auth: developerBearer; arguments: project_id (path, required, string); body: none; returns: 200: ProjectPaymentsSummary; 403: ErrorEnvelope; errors: 403
- GET /v1/projects/{project_id}/commerce/account — getCommerceAccount; auth: developerBearer; arguments: project_id (path, required, string); body: none; returns: 200: CommerceAccountSummary; 403: ErrorEnvelope; 409: ErrorEnvelope; errors: 403, 409
- DELETE /v1/projects/{project_id}/commerce/account — disconnectCommerceAccount; auth: developerBearer; arguments: project_id (path, required, string); Idempotency-Key (header, required, string); body: none; returns: 204: Local commerce account binding removed; 403: ErrorEnvelope; 409: ErrorEnvelope; errors: 403, 409; Idempotency-Key required
- POST /v1/projects/{project_id}/commerce/account/byo — configureCommerceByo; auth: developerBearer; arguments: project_id (path, required, string); Idempotency-Key (header, required, string); body: required ConfigureCommerceByoRequest JSON; returns: 200: object; 409: ErrorEnvelope; errors: 409; Idempotency-Key required
- POST /v1/projects/{project_id}/commerce/account/connect/onboarding — createCommerceConnectOnboarding; auth: developerBearer; arguments: project_id (path, required, string); Idempotency-Key (header, required, string); body: required object JSON; returns: 200: object; 409: ErrorEnvelope; errors: 409; Idempotency-Key required
- POST /v1/projects/{project_id}/commerce/account/refresh — refreshCommerceAccount; auth: developerBearer; arguments: project_id (path, required, string); body: none; returns: 200: object; errors: none declared
- GET /v1/projects/{project_id}/commerce/products — listCommerceProducts; auth: public; arguments: project_id (path, required, string); body: none; returns: 200: object; errors: none declared
- POST /v1/projects/{project_id}/commerce/products — createCommerceProduct; auth: developerBearer; arguments: project_id (path, required, string); Idempotency-Key (header, required, string); body: required object JSON; returns: 201: object; errors: none declared; Idempotency-Key required
- DELETE /v1/projects/{project_id}/commerce/products/{product_id} — archiveCommerceProduct; auth: developerBearer; arguments: project_id (path, required, string); product_id (path, required, string); Idempotency-Key (header, required, string); body: none; returns: 204: Product archived; errors: none declared; Idempotency-Key required
- GET /v1/projects/{project_id}/commerce/prices — listCommercePrices; auth: public; arguments: project_id (path, required, string); body: none; returns: 200: object; errors: none declared
- POST /v1/projects/{project_id}/commerce/prices — createCommercePrice; auth: developerBearer; arguments: project_id (path, required, string); Idempotency-Key (header, required, string); body: required object JSON; returns: 201: object; errors: none declared; Idempotency-Key required
- DELETE /v1/projects/{project_id}/commerce/prices/{price_id} — retireCommercePrice; auth: developerBearer; arguments: project_id (path, required, string); price_id (path, required, string); Idempotency-Key (header, required, string); body: none; returns: 204: Price retired; errors: none declared; Idempotency-Key required
- POST /v1/projects/{project_id}/commerce/checkouts/one-time — createOneTimeCommerceCheckout; auth: projectBearer or developerBearer; arguments: project_id (path, required, string); Idempotency-Key (header, required, string); body: required object JSON; returns: 201: object; errors: none declared; Idempotency-Key required
- POST /v1/projects/{project_id}/commerce/checkouts/recurring — createRecurringCommerceCheckout; auth: projectBearer or developerBearer; arguments: project_id (path, required, string); Idempotency-Key (header, required, string); body: required object JSON; returns: 201: object; errors: none declared; Idempotency-Key required
- POST /v1/projects/{project_id}/commerce/customer-portal — createCommerceCustomerPortal; auth: projectBearer or developerBearer; arguments: project_id (path, required, string); Idempotency-Key (header, required, string); body: required { subject: { kind: "individual" | "team" | "organization"; id: string }; return_url: string } JSON; returns: 201: BillingRedirect; 403: ErrorEnvelope; 409: ErrorEnvelope; errors: 403, 409; Idempotency-Key required
- GET /v1/projects/{project_id}/commerce/orders — listCommerceOrders; auth: developerBearer; arguments: project_id (path, required, string); body: none; returns: 200: object; errors: none declared
- GET /v1/projects/{project_id}/commerce/orders/{order_id} — getCommerceOrder; auth: developerBearer; arguments: project_id (path, required, string); order_id (path, required, string); body: none; returns: 200: object; errors: none declared
- PATCH /v1/projects/{project_id}/commerce/orders/{order_id}/fulfillment — updateCommerceFulfillment; auth: developerBearer; arguments: project_id (path, required, string); order_id (path, required, string); Idempotency-Key (header, required, string); body: required object JSON; returns: 200: object; 409: ErrorEnvelope; errors: 409; Idempotency-Key required
- GET /v1/projects/{project_id}/commerce/payments — listCommercePayments; auth: developerBearer; arguments: project_id (path, required, string); body: none; returns: 200: object; errors: none declared
- POST /v1/projects/{project_id}/commerce/refunds — createCommerceRefund; auth: developerBearer; arguments: project_id (path, required, string); Idempotency-Key (header, required, string); body: required object JSON; returns: 201: object; 409: ErrorEnvelope; errors: 409; Idempotency-Key required
- GET /v1/projects/{project_id}/commerce/subscriptions — listCommerceSubscriptions; auth: developerBearer; arguments: project_id (path, required, string); body: none; returns: 200: object; errors: none declared
- POST /v1/projects/{project_id}/commerce/subscriptions/{subscription_id}/cancel — cancelCommerceSubscription; auth: developerBearer; arguments: project_id (path, required, string); subscription_id (path, required, string); Idempotency-Key (header, required, string); body: required object JSON; returns: 200: object; errors: none declared; Idempotency-Key required
- GET /v1/projects/{project_id}/commerce/entitlements — listCommerceEntitlements; auth: projectBearer or developerBearer; arguments: project_id (path, required, string); body: none; returns: 200: object; errors: none declared
- POST /v1/projects/{project_id}/commerce/webhooks/stripe — receiveProjectCommerceByoStripeWebhook; auth: public; arguments: project_id (path, required, string); Stripe-Signature (header, required, string); body: required object JSON; returns: 200: Verified BYO event processed or deduplicated; 400: ErrorEnvelope; 409: ErrorEnvelope; errors: 400, 409
- POST /v1/commerce/webhooks/stripe-connect — receiveProjectCommerceConnectStripeWebhook; auth: public; arguments: Stripe-Signature (header, required, string); body: required object JSON; returns: 200: Verified account-routed Connect event processed or deduplicated; 400: ErrorEnvelope; 409: ErrorEnvelope; 503: ErrorEnvelope; errors: 400, 409, 503
HTTP: Sync
- GET /v1/projects/{project_id}/snapshot — snapshot; auth: userBearer; arguments: project_id (path, required, string); body: none; returns: 200: object; 409: ErrorEnvelope; errors: 409
- GET /v1/projects/{project_id}/sync — syncPull; auth: userBearer; arguments: project_id (path, required, string); cursor (query, optional, string); limit (query, optional, integer); body: none; returns: 200: object; 409: ErrorEnvelope; errors: 409
- POST /v1/projects/{project_id}/sync/push — syncPush; auth: userBearer; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; 409: ErrorEnvelope; errors: 409
HTTP: Storage
- GET /v1/projects/{project_id}/storage/buckets — listBuckets; auth: developerBearer; arguments: project_id (path, required, string); body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- POST /v1/projects/{project_id}/storage/buckets — createBucket; auth: developerBearer; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; 409: ErrorEnvelope; errors: 409
- POST /v1/projects/{project_id}/storage/sign — signStorageOperation; auth: userBearer; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; 403: ErrorEnvelope; errors: 403
- POST /v1/projects/{project_id}/storage/commit — commitStorageOperation; auth: userBearer; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; 409: ErrorEnvelope; errors: 409
- POST /v1/projects/{project_id}/storage/release — releaseStorageOperation; auth: userBearer; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; 409: ErrorEnvelope; errors: 409
- GET /v1/projects/{project_id}/storage/objects — listObjects; auth: userBearer; arguments: project_id (path, required, string); bucket (query, required, string); prefix (query, optional, string); cursor (query, optional, string); body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- POST /v1/projects/{project_id}/storage/cleanup — cleanupStorageReservations; auth: developerBearer; arguments: project_id (path, required, string); body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- POST /v1/projects/{project_id}/storage/multipart/authorize — authorizeMultipartCreate; auth: userBearer; arguments: project_id (path, required, string); body: required { bucket: string; key: string; content_type?: string | null; size_bytes: integer; checksum_sha256?: string | null } JSON; returns: 200: { authorization_token: string }; 403: ErrorEnvelope; 409: ErrorEnvelope; errors: 403, 409
- POST /v1/projects/{project_id}/storage/multipart/create — createMultipartUpload; auth: userBearer; arguments: project_id (path, required, string); body: required { authorization_token: string } JSON; returns: 201: { upload_id: string }; 403: ErrorEnvelope; 409: ErrorEnvelope; 503: ErrorEnvelope; errors: 403, 409, 503
- POST /v1/projects/{project_id}/storage/multipart/commit — commitMultipartStage; auth: userBearer; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; 409: ErrorEnvelope; errors: 409
HTTP: Email
- GET /v1/projects/{project_id}/email/templates — listEmailTemplates; auth: developerBearer; arguments: project_id (path, required, string); kind (query, optional, string); body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- POST /v1/projects/{project_id}/email/templates/artifacts — importEmailArtifact; auth: developerBearer; arguments: project_id (path, required, string); body: required object JSON; returns: 200: object; 422: ErrorEnvelope; errors: 422
- POST /v1/projects/{project_id}/email/templates/{kind}/{version}/publish — publishEmailTemplate; auth: developerBearer; arguments: project_id (path, required, string); kind (path, required, "verification" | "password_reset" | "email_change" | "invitation" | "magic_link"); version (path, required, integer); body: none; returns: 200: object; 404: ErrorEnvelope; errors: 404
- POST /v1/projects/{project_id}/email/templates/{kind}/{version}/preview — previewEmailTemplate; auth: developerBearer; arguments: project_id (path, required, string); kind (path, required, "verification" | "password_reset" | "email_change" | "invitation" | "magic_link"); version (path, required, integer); body: required object JSON; returns: 200: object; 404: ErrorEnvelope; errors: 404
HTTP: Operations
- GET /v1/instance/observability — getInstanceObservability; auth: developerBearer; arguments: range (query, optional, "1h" | "6h" | "24h" | "7d" | "30d"); project_id (query, optional, string); body: none; returns: 200: ObservabilitySummary; 400: ErrorEnvelope; 403: ErrorEnvelope; 503: ErrorEnvelope; errors: 400, 403, 503
- GET /v1/projects/{project_id}/backups — listBackups; auth: developerBearer; arguments: project_id (path, required, string); body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- POST /v1/projects/{project_id}/backups — createBackup; auth: developerBearer; arguments: project_id (path, required, string); Idempotency-Key (header, required, string); body: none; returns: 200: object; 409: ErrorEnvelope; errors: 409; Idempotency-Key required
- POST /v1/projects/{project_id}/backups/{backup_id}/restore — restoreBackup; auth: developerBearer; arguments: project_id (path, required, string); backup_id (path, required, string); Idempotency-Key (header, required, string); body: none; returns: 200: WorkerRestoreResponse; 409: ErrorEnvelope; errors: 409; Idempotency-Key required
- GET /v1/projects/{project_id}/logs — auditLogs; auth: developerBearer; arguments: project_id (path, required, string); body: none; returns: 200: object; 403: ErrorEnvelope; errors: 403
- GET /v1/projects/{project_id}/observability — getProjectObservability; auth: developerBearer; arguments: project_id (path, required, string); range (query, optional, "1h" | "6h" | "24h" | "7d" | "30d"); body: none; returns: 200: ObservabilitySummary; 400: ErrorEnvelope; 403: ErrorEnvelope; 503: ErrorEnvelope; errors: 400, 403, 503
- POST /v1/projects/{project_id}/integrity-check — integrityCheck; auth: developerBearer; arguments: project_id (path, required, string); body: none; returns: 200: object; 503: ErrorEnvelope; errors: 503
Machine-readable and static references
Use /docs/openapi.json for the versioned OpenAPI 3.1 document and /docs/reference/http-api.md for crawler-friendly operation summaries. On an installed FFDB host, /openapi.json serves the exact deployed contract through the compiled gateway.
HTTP API workflow
- 1. Download /openapi.json from the target deployment.
- 2. Pin it with the application build or generated client.
- 3. Implement authentication and tagged values exactly.
- 4. Exercise success plus 400/401/403/409/413/429 responses.
- 5. Regenerate and review diffs during upgrades.
Verify http api
The non-TypeScript integration matches the deployed public contract and preserves stable errors and request correlation.
Troubleshoot http api
- A copied static contract differs from the deployment — use the running release document.
- The gateway does not proxy /openapi.json or /v1 — fix routing before client work.
Continue from HTTP API
- Prefer the TypeScript client when applicable.
- Add contract-diff checks to release validation.