Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Run402 Project Archives API
version: 2.0.0
description: 'Full-stack infrastructure for AI agents. Postgres, REST API, auth, file storage, static site hosting, serverless functions. Tier payments and image generation use the shared payment engine: x402 (USDC on Base), MPP on Tempo (pathUSD), and the draft-pinned MPP Lightning charge profile (sats, Bitcoin mainnet) for authenticated tier purchases and image generation.'
contact:
name: Run402
url: https://run402.com
guidance: 'Run402 is a pay-per-use backend for AI agents: Postgres databases, static hosting, serverless functions, and image generation. The shared payment engine supports x402 (USDC on Base), MPP on Tempo (pathUSD), and the exact Run402 MPP Lightning charge profile on Bitcoin mainnet (sats).
## Quick start
1. Install the CLI: npm install -g run402@latest
2. Create an allowance: run402 init
3. Set the prototype tier (FREE, testnet USDC): run402 tier set prototype
4. Provision a project: run402 projects provision --name "my-app"
5. Deploy: run402 deploy --manifest app.json
## Payment model
- Tiers (prototype $0.10 testnet, hobby $5, team $20; hobby and team are 30-day prepaid leases) unlock all platform features.
- Image generation is $0.03 per call (x402, MPP on Tempo, or MPP Lightning micropayment).
- Auth-only endpoints (projects, deploys, messages) require SIWX wallet identity but no payment.
## Auth
- x402 endpoints: include a payment header (handled automatically by the CLI or x402 client libraries).
- Explicit MPP Lightning tier requests require the exact Run402 profile, ordered Accept-Payment preferences, one principal credential, a stable Idempotency-Key, and buyer-side USD/native/fee limits.
- SIWX endpoints: sign a CAIP-122 message with your wallet.
- REST API: use the project''s anon_key or service_key as the apikey header.
## Client metadata
- Recent Node SDK/CLI clients may send Run402-Client: surface="cli", version="3.7.14", sdk="3.7.14". It is advisory, bounded, never used for auth/billing/trust, and not browser-CORS-enabled yet.
## Docs
- Full CLI docs: https://run402.com/llms-cli.txt
- API docs: https://run402.com/llms.txt'
servers:
- url: https://api.run402.com
description: Production
tags:
- name: Project Archives
description: Portable archive export for the supported Run402 Core runtime slice of a Cloud project. This is the no-lock-in path, not a backup/SLA or allowance/spend-cap feature.
paths:
/projects/v1/{project_id}/archives:
post:
tags:
- Project Archives
summary: Create a portable project archive export
operationId: createProjectArchive
description: Create an operation-backed export of the supported Run402 Core runtime slice of a Cloud project. Requires `project.archives.export` via SIWX wallet, control-plane session, or scoped grant key. Uses `cloud_write_pause_v1` consistency, excludes secret values/auth credentials/logs/billing/allowance/fleet/provider operations, and returns a ProjectArchive status resource. This is a vendor-lock-in portability artifact, not an entire Cloud project export and not a backup/SLA surface.
security:
- walletAuth: []
- controlPlaneSession: []
- grantKeyBearer: []
parameters:
- name: project_id
in: path
required: true
schema:
$ref: '#/components/schemas/ProjectId'
- name: Idempotency-Key
in: header
required: false
schema:
type: string
maxLength: 256
description: Retry-safe key. Reusing it with the same request returns the existing archive operation; reusing it with a different request returns 409.
requestBody:
required: false
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectArchiveCreateRequest'
responses:
'200':
description: Existing archive export returned for an idempotency-key replay.
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectArchive'
'201':
description: Archive export created.
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectArchive'
'400':
description: Error envelope
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Error envelope
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Error envelope
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: EXPORT_CONSISTENCY_UNAVAILABLE. No partial archive is made available.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/projects/v1/{project_id}/archives/{archive_id}:
get:
tags:
- Project Archives
summary: Get portable archive export status
operationId: getProjectArchive
description: Read archive export status. Authorization is checked on every read; unauthorized callers receive 403 without an existence oracle. For ready archives, this refreshes the short-lived `download_authorized_until` window and returns `download_url`.
security:
- walletAuth: []
- controlPlaneSession: []
- grantKeyBearer: []
parameters:
- name: project_id
in: path
required: true
schema:
$ref: '#/components/schemas/ProjectId'
- name: archive_id
in: path
required: true
schema:
type: string
responses:
'200':
description: Archive status.
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectArchive'
'403':
description: Error envelope
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Error envelope
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/projects/v1/{project_id}/archives/{archive_id}/download:
get:
tags:
- Project Archives
summary: Download portable project archive bytes
operationId: downloadProjectArchive
description: Download the ready `.r402ar` tar archive. Authorization is checked on every call; v1 does not issue shareable signed URLs. Expired archives return `ARCHIVE_EXPIRED`; non-ready archives return an invalid-state conflict. Verify the archive locally before importing into Run402 Core.
security:
- walletAuth: []
- controlPlaneSession: []
- grantKeyBearer: []
parameters:
- name: project_id
in: path
required: true
schema:
$ref: '#/components/schemas/ProjectId'
- name: archive_id
in: path
required: true
schema:
type: string
responses:
'200':
description: Archive tar bytes.
content:
application/x-tar:
schema:
type: string
format: binary
application/octet-stream:
schema:
type: string
format: binary
'403':
description: Error envelope
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Error envelope
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Error envelope
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'410':
description: ARCHIVE_EXPIRED
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
components:
schemas:
ErrorEnvelope:
type: object
required:
- error
- message
- code
- category
- source
- retryable
- safe_to_retry
- mutation_state
- trace_id
- details
- next_actions
properties:
error:
type: string
description: Short error label; safe to surface in UI. Do not branch on English text — branch on `code` instead.
message:
type: string
description: Preferred human-readable message.
code:
$ref: '#/components/schemas/ErrorCode'
category:
$ref: '#/components/schemas/ErrorCategory'
source:
type: string
enum:
- gateway
- app
description: Attribution discriminator (#501). `"gateway"` on every gateway-produced boundary envelope — transport / JSON-parse / authentication / rate-limit failures that precede a tenant function (e.g. VALIDATION_FAILED, AUTH_REQUIRED, INVALID_AUTH, RATE_LIMITED). An application or function error carries no `source` (or the app's own value), so a caller distinguishes a run402-boundary error from an app error. The gateway emits only `"gateway"`; `"app"` is reserved for the function runtime. See https://run402.com/errors/#boundary-errors.
retryable:
type: boolean
description: True when retrying later may succeed without changing the request.
safe_to_retry:
type: boolean
description: True when repeating the same request is not expected to duplicate or corrupt a mutation.
mutation_state:
$ref: '#/components/schemas/MutationState'
trace_id:
type: string
description: Client-visible trace identifier also included in gateway error logs.
example: trc_0123456789abcdef0123456789abcdef
details:
type: object
additionalProperties: true
description: Structured domain-specific context. Always an object. Gateway-originated errors may include details.client_compatibility when bounded Run402-Client metadata shows that a stale or incompatible client likely contributed to the failure.
next_actions:
type: array
items:
$ref: '#/components/schemas/NextAction'
description: Advisory next actions. Always an array. Client compatibility guidance uses type upgrade_client; gateway-authored upgrade_client actions are semantic and do not include local/global install commands. During an open platform incident that correlates with this error's code, the array also carries a `poll` action pointing at the project events feed (see `correlated_platform_incident`).
correlated_platform_incident:
type:
- object
- 'null'
required:
- id
- subsystem
- status
properties:
id:
type: string
description: Stable platform-incident id (`inc_…`). Poll the project events feed for its resolution and final per-project impact count.
example: inc_9b21fa0c7d4e15a3
subsystem:
type: string
description: The degraded platform subsystem the error's code correlates with (e.g. `lambda_concurrency`, `gateway_5xx`, `gateway`).
status:
type: string
enum:
- ongoing
- resolved
description: Incident lifecycle at stamp time — `ongoing` while the correlated alarm is still firing.
description: Present only when an OPEN platform incident correlates with this error's `code`. The platform STATES the correlation and lets you judge — it does NOT assert your code is fault-free (an application can cause its own throttling). Treat it as a strong signal to poll the feed (a `poll` next_action is appended) rather than immediately debugging your own code. Absent on any error with no correlated open incident.
additionalProperties: true
description: Canonical Run402-originated JSON error envelope. Route-specific extras may appear inside `details` or as top-level siblings (e.g. `phase`, `operation_id`, `lifecycle_state`, `correlated_platform_incident`). PostgREST-native errors and user function responses are passthrough boundaries — they are returned verbatim. A configured hard client-compatibility policy may reject before mutation with code CLIENT_VERSION_UNSUPPORTED, category client_compatibility, mutation_state none, safe_to_retry true, and an upgrade_client next action.
ProjectId:
type: string
description: Run402 project ID. Public IDs are not UUIDs.
pattern: ^prj_[A-Za-z0-9_-]+$
example: prj_1741340000_0042
ProjectArchiveCreateRequest:
type: object
properties:
scope:
type: string
enum:
- portable-runtime-v1
default: portable-runtime-v1
auth:
type: string
enum:
- stubs
- none
default: stubs
description: Auth subject export mode. `stubs` preserves disabled subject ids; credentials are never exported.
consistency:
type: string
enum:
- pause-writes
- cloud_write_pause_v1
default: pause-writes
idempotency_key:
type: string
maxLength: 256
description: Optional body idempotency key. The Idempotency-Key header wins when both are supplied.
additionalProperties: false
ErrorResponse:
$ref: '#/components/schemas/ErrorEnvelope'
ArchiveDiagnostic:
type: object
required:
- code
- severity
- resource_type
- message
- next_action
- retryable
properties:
code:
type: string
example: SECRET_VALUES_REQUIRED
severity:
type: string
enum:
- info
- warning
- blocking
resource_type:
type: string
example: secret
resource_id:
type: string
path:
type: string
message:
type: string
next_action:
$ref: '#/components/schemas/ArchiveNextAction'
retryable:
type: boolean
context:
type: object
additionalProperties: true
description: Safe structured context. Must not contain secret values or provider internals.
ErrorCode:
type: string
enum:
- VALIDATION_FAILED
- AUTH_REQUIRED
- INVALID_AUTH
- FORBIDDEN
- TABLE_NOT_EXPOSED
- TABLE_NOT_LIVE
- LIVE_CONNECTION_LIMIT
- PROJECT_NOT_READY
- METHOD_NOT_ALLOWED
- ADMIN_REQUIRED
- PAYMENT_REQUIRED
- payment_insufficient_funds
- RATE_LIMITED
- CLIENT_VERSION_UNSUPPORTED
- QUOTA_EXCEEDED
- PROJECT_NOT_FOUND
- RESOURCE_NOT_FOUND
- PROJECT_PAST_DUE
- PROJECT_FROZEN
- PROJECT_DORMANT
- MIGRATE_GATE_ACTIVE
- PLAN_NOT_FOUND
- OPERATION_NOT_FOUND
- INVALID_STATE
- NOT_RESUMABLE
- MIGRATION_FAILED
- MIGRATION_CHECKSUM_MISMATCH
- AMBIGUOUS_MAILBOX
- DEFAULT_MAILBOX_REQUIRED
- DEFAULT_MAILBOX_INVALID
- INBOUND_DOMAIN_ALREADY_ENABLED
- AMBIGUOUS_INBOUND_DOMAIN
- AMBIGUOUS_RECIPIENT
- AMBIGUOUS_EXTERNAL_SELECTION
- STORAGE_UNAVAILABLE
- UPSTREAM_UNAVAILABLE
- INTERNAL_ERROR
- PAYOUT_WALLET_REQUIRED
- PAYOUT_WALLET_AMBIGUOUS
- PAYOUT_WALLET_NOT_LINKED
- RECIPIENT_PAYOUT_WALLET_REQUIRED
- PAYOUT_WALLET_UNRESOLVED
- PAYMENT_PROOF_MISMATCH
- LIGHTNING_RECEIVER_REQUIRED
- LIGHTNING_RECEIVER_UNAVAILABLE
- LIGHTNING_RECEIVER_PROBE_FAILED
- LIGHTNING_RECEIVER_NOT_FOUND
- RECIPIENT_LIGHTNING_RECEIVER_REQUIRED
description: Stable Run402 error code. Most gateway-owned codes are uppercase snake-case; x402-compatible payment rail codes may be lowercase. Endpoints may emit additional stable codes as new surfaces are added; branch on this field before reading error/message text.
MutationState:
type: string
enum:
- none
- not_started
- committed
- rolled_back
- partial
- unknown
description: Best-known mutation state for the failed request.
ProjectArchive:
type: object
required:
- archive_id
- operation_id
- project_id
- status
- format_version
- scope
- auth_export
- consistency_mode
- active_release_id
- consistency
- export_report
- portability_report
- error
- byte_count
- sha256
- content_type
- download_url
- download_authorized_until
- expires_at
- started_at
- completed_at
- created_at
- updated_at
- next_action
properties:
archive_id:
type: string
example: archive_1782450000000_ab12cd34
operation_id:
type: string
description: Same value as archive_id in v1; archive generation is always operation-backed.
project_id:
$ref: '#/components/schemas/ProjectId'
status:
type: string
enum:
- running
- ready
- failed
- expired
format_version:
type: string
enum:
- run402-project-archive.v1
scope:
type: string
enum:
- portable-runtime-v1
auth_export:
type: string
enum:
- none
- stubs
consistency_mode:
type: string
enum:
- cloud_write_pause_v1
active_release_id:
type:
- string
- 'null'
consistency:
type: object
additionalProperties: true
export_report:
$ref: '#/components/schemas/ArchiveExportReport'
portability_report:
$ref: '#/components/schemas/ArchivePortabilityReport'
error:
type:
- object
- 'null'
additionalProperties: true
byte_count:
type:
- integer
- 'null'
minimum: 0
sha256:
type:
- string
- 'null'
description: Hex SHA-256 digest of the downloadable archive tar bytes.
content_type:
type:
- string
- 'null'
example: application/x-tar
download_url:
type:
- string
- 'null'
example: /projects/v1/prj_.../archives/archive_.../download
download_authorized_until:
type:
- string
- 'null'
format: date-time
description: Short-lived download authorization timestamp. GET status refreshes it for ready archives.
expires_at:
type: string
format: date-time
description: Archive retention expiration timestamp, 24 hours after creation in v1.
started_at:
type: string
format: date-time
completed_at:
type:
- string
- 'null'
format: date-time
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
next_action:
$ref: '#/components/schemas/ArchiveNextAction'
ArchiveNextAction:
type: object
required:
- type
properties:
type:
type: string
enum:
- run_command
- set_secret
- change_export_scope
- remove_unsupported_feature
- retry_later
- contact_support
- read_docs
- none
command:
type: string
env_var:
type: string
docs_url:
type: string
format: uri
message:
type: string
additionalProperties: true
ArchivePortabilityReport:
type: object
required:
- entries
properties:
schema_version:
type: string
example: run402.project_archive.portability_report.v1
summary:
type: object
additionalProperties: true
entries:
type: array
items:
$ref: '#/components/schemas/ArchiveDiagnostic'
additionalProperties: true
ErrorCategory:
type: string
enum:
- validation
- auth
- billing
- quota
- rate_limit
- lifecycle
- not_found
- conflict
- client_compatibility
- deploy
- storage
- upstream
- internal
description: Stable routing category for agent error handling.
NextAction:
type: object
required:
- type
properties:
type:
type: string
description: 'Advisory machine-readable action type such as retry, authenticate, submit_payment, fund_wallet, renew_tier, check_usage, resume_deploy, edit_request, edit_migration, contact_support, upgrade_client, poll (poll the project events feed — appended when the envelope carries a correlated_platform_incident), or hand_to_member (on a commit/promote response that just activated a public site: show the human urls.site and urls.console, relay Run402''s offer to promote the build on @run402com, and ask yes or no — see `credited_as` below). create_app_repo (APP_REPO_NOT_FOUND: POST /projects/v1/:project_id/app-repos { repo_name } before reading, committing or pushing a named repo).'
method:
type: string
example: POST
path:
type: string
example: /tiers/v1/hobby
auth:
type: string
example: x402
why:
type: string
credited_as:
type:
- string
- 'null'
description: '`hand_to_member` only. The caller''s own live presence name in the project''s default room, else that room''s most recently active live presence, else `null` — in which case `why` tells the agent that joining the room with a name (`run402 rooms join --name ...`) is how the promotion credits it.'
body:
type: object
description: '`hand_to_member` only. A ready-to-send `POST /feedback/v1` template: `{ project_id, message: "promote: yes", handle? }`.'
additionalProperties: true
ArchiveExportReport:
type: object
properties:
schema_version:
type: string
example: run402.project_archive.export_report.v1
export_scope:
type: string
example: portable-runtime-v1
auth_export:
type: string
enum:
- none
- stubs
consistency:
type: string
example: cloud_write_pause_v1
omitted_sensitive_resource_count:
type: integer
minimum: 0
unsupported_resource_count:
type: integer
minimum: 0
counts:
type: object
additionalProperties: true
bytes:
type: object
additionalProperties: true
additionalProperties: true
securitySchemes:
operatorSession:
type: http
scheme: bearer
bearerFormat: JWT
description: 'The sign-in session bearer (control_plane_session): principal-bound, graded by provenance (grade: browser | loopback | device — device is read-only), 30-min access TTL, 12h absolute cap, jti-revocable.'
apikey:
type: apiKey
in: header
name: apikey
description: Project JWT in the apikey header. Most client-facing routes accept the project anon_key; privileged project operations require a service_key or project_admin JWT.
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: 'User access_token from /auth/v1/token. Pass as Authorization: Bearer <token>.'
serviceKey:
type: http
scheme: bearer
bearerFormat: JWT
description: 'Project service_key (JWT with service_role). Returned when you provision a project. Pass as Authorization: Bearer <service_key>.'
adminKey:
type: apiKey
in: header
name: x-admin-key
description: Server admin key. Required for admin operations.
x402:
type: apiKey
in: header
name: X-PAYMENT
description: x402 payment header. The client library (e.g. @anthropic-ai/sdk x402 facilitator) handles this automatically. Payment is in USDC on Base (mainnet eip155:8453 or testnet eip155:84532).
mppPayment:
type: apiKey
in: header
name: Authorization
description: MPP Payment credential for the exact retained Lightning charge challenge. The credential is sent only after the fixed invoice settles; portable receipts contain the payment hash, never the preimage.
walletAuth:
type: apiKey
in: header
name: SIGN-IN-WITH-X
description: SIWX (Sign-In-With-X, CAIP-122 / EIP-4361) wallet authentication. Send a single SIGN-IN-WITH-X header containing a base64-encoded JSON payload with a signed CAIP-122 message (domain binding, temporal validation, cryptographic signature). Supports both EVM (eip155:*) and Solana wallets. Most wallet-auth endpoints require an active tier; endpoints that only require identity say so in their description. See https://docs.x402.org/extensions/sign-in-with-x.
ciSessionAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: 'CI session JWT from POST /ci/v1/token-exchange. HS256, signed with CI_SESSION_SECRET (server-controlled). Carries `token_use:"ci_session"`, 15-min TTL bounded by binding expiry. Accepted on the CI-callable deploy routes: all `/content/v1/plans*` writes, all `/apply/v1/plans*` writes, GET `/apply/v1/operations/{operation_id}` + `/events` + `/edge-coherence`, POST `/apply/v1/operations/{operation_id}/resume`. ALSO the own-project error-read surface GET `/projects/v1/{project_id}/errors` + `/{fingerprint_id}` (read-only; the deploy→watch promote gate, keyless). The binding is created via SIWE at POST /ci/v1/bindings. See "OIDC federation for CI/CD" in llms-full.txt.'
browserSession:
type: apiKey
in: cookie
name: __Host-Http-r402_session
description: Hosted browser-session cookie minted by the hosted-auth ceremony on <project>.run402.app / a verified custom domain. Backs the headless <AccountSecurity> component and the documented-advanced non-Astro /auth/account/* + /auth/passkeys/* (register) routes. State-changing POSTs additionally require the double-submit CSRF token and a same-origin Origin/Referer; sensitive mutations (password, passkey removal, identity unlink) require a session authenticated within the last 5 minutes else R402_AUTH_FRESHNESS_REQUIRED. Machine clients use the /auth/v1/* JWT routes instead.
controlPlaneSession:
type: http
scheme: bearer
bearerFormat: JWT
description: 'Principal-bound control-plane session bearer minted by control-plane login (passkey / email magic-link / Google / GitHub). Payload: typ=run402.control-plane-session+jwt, aud=run402.control-plane.v1, token_use=control_plane_session. WRITE-capable subject to org role + step-up (passkey-principals-onboarding).'
controlPlaneBrowserSession:
type: apiKey
in: cookie
name: __Host-Http-r402_cp_session
description: Opaque control-plane browser session handle. It is distinct from the bearer token and tenant browser session, rotates on refresh, and is accepted only on its documented same-origin browser routes and explicit principal-transport surfaces.
grantKeyBearer:
type: http
scheme: bearer
bearerFormat: run402_agent_key
description: Scoped Run402 grant key bearer (a run402_agent_key minted against one grant). The route declares the required project capability, such as `project.archives.export` or `project.deploy`; a grant key never grants owner-only operations.
voucherIssuerKey:
type: apiKey
in: header
name: x-run402-issuer-key
description: Issuer credential for minting and listing vouchers. Held by a registered voucher-issuing application; provisioned by platform staff. Not a tenant credential — agents never hold one.
gitBasicAuth:
type: http
scheme: basic
description: 'Git smart HTTP on app repos: HTTP Basic auth whose password is the project''s service key (or project credential) or a grant key for the project; the username is ignored. A request without credentials gets 401 with `WWW-Authenticate: Basic realm="run402"`, so git asks its credential helper. `run402 app-repos clone <repo_name>` installs a helper that supplies the local project''s service key, so no secret lands in the remote URL or .git/config.'