Veto/docs
Meow Gateway

API reference

Every REST endpoint exposed by the meow-gateway. Stripe-tier error envelope on every non-2xx.

Base URL (self-host): http://localhost:3005 Base URL (managed): https://gateway.veto.so

Every non-2xx response uses the same envelope:

{
  "error": {
    "type": "invalid_request",
    "code": "capsule_payload_invalid",
    "message": "...",
    "param": "...",
    "doc_url": "https://docs.veto.so/docs/meow/errors/capsule_payload_invalid",
    "hint": "...",
    "request_id": "req_01hy2z...",
    "capsule_id": "cap_...",
    "approval_id": "apr_...",
    "payload_hash": "sha256:..."
  }
}

Public surface (no auth)

MethodPathPurpose
GET/healthLiveness
GET/readyReadiness (storage + signing)
GET/.well-known/veto-keys.jsonJWKS

Authenticated surface

All routes below require X-API-Key: <api_key>. In self-host loopback mode without VETO_API_KEYS set, the gateway treats every request as organization_id = self-host — fine for local dev.

Capsules

MethodPathPurpose
POST/v1/capsulesMint
GET/v1/capsules/:idStatus
POST/v1/capsules/:id/revokeRevoke

Consume

MethodPathPurpose
POST/meow/consumeREST consume
POST/meow/mcpMCP server (tools/list, tools/call)

Receipts

MethodPathPurpose
GET/v1/receipts/:entity_idList (supports ?from=&to=&limit=)
GET/v1/receipts/:entity_id/verifyServer-side chain verify
GET/v1/receipts/:entity_id/tipMost recent receipt hash

Counterparties

MethodPathPurpose
GET/v1/counterpartiesList (filter: held / unverified / verified / all)
POST/v1/counterpartiesUpsert
GET/v1/counterparties/:hashFetch
POST/v1/counterparties/:hash/verifyExit quarantine
POST/v1/counterparties/:hash/holdImmediate-reject on drift

Workflows

MethodPathPurpose
POST/v1/workflowsCreate (state=draft)
GET/v1/workflows/:idFetch
GET/v1/workflowsList
POST/v1/workflows/:id/transitionsState transition

Budgets

MethodPathPurpose
POST/v1/budgets/:entity_idUpsert caps
GET/v1/budgets/:entity_idFetch caps + live usage gauges
GET/v1/budgets/:entity_id/leasesOutstanding leases

Invoices

MethodPathPurpose
POST/v1/invoicesIngest bytes_base64
GET/v1/invoices/:idFetch
GET/v1/invoicesList
GET/v1/invoices/by-hash/:hashFetch by content hash

Approvals

MethodPathPurpose
GET/v1/approvalsList
GET/v1/approvals/:idFetch
POST/v1/approvals/:id/resolveApprove / deny

Onboarding

MethodPathPurpose
POST/v1/onboarding/applicationsCreate
GET/v1/onboarding/applicationsList
GET/v1/onboarding/applications/:idFetch
POST/v1/onboarding/applications/:id/documentsUpload doc hash
POST/v1/onboarding/applications/:id/policySelect pack
GET/v1/onboarding/applications/:id/reviewReadiness check
POST/v1/onboarding/applications/:id/submitSeal genesis + submit
POST/v1/onboarding/applications/:id/decisionOperator approve/reject

Routing

MethodPathPurpose
POST/v1/routing/suggestPick a rail

Meow OAuth (managed only)

MethodPathPurpose
GET/v1/meow/oauth/authorizeStart flow
GET/v1/meow/oauth/callbackBrowser redirect target
DELETE/v1/meow/oauth/sessionRevoke

Webhooks (Meow → gateway)

MethodPathPurpose
POST/webhooks/meowHMAC-authenticated settlement + status events

Idempotency

Mint accepts Idempotency-Key: <string>. Retries with the same key AND canonical body return the original 200 + JWS. Retries with the same key but different body return 400 idempotency_key_reused_with_different_payload.

OpenAPI

Once published, the full OpenAPI 3.1 lives at <base>/openapi.yaml. Block 7 scope tracks parity between this table and the generated spec.