Docs
Every route the real OpenMoney API serves, generated from the same Zod route schemas that run in production and rendered here live from the API's own GET /v1/openapi.json — a new or changed route appears the next time this page loads, with nothing hand-maintained in between.
https://api.openmoney.ai (production environment)Authorization: Bearer om_test_… / om_live_…) for everything else. Every mutating route also requires an Idempotency-Key header.application/problem+json on every non-2xx response — type, title, status, detail, instance.1 route
Liveness and dependency checks.
/healthDependency healthRuns real checks: `SELECT 1`, Redis `PING`, an S3 `HeadBucket`, and an SMTP handshake (results cached 30 s). Returns 503 when Postgres or Redis fail; storage/email problems only mark the service degraded.
Auth: Public — no session or key required
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 429 | application/problem+json | Rate limited — retry after the `Retry-After` seconds. |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 503 | application/json | Default Response |
1 route
Provider configuration status (sandbox/live/unconfigured).
/v1/status/providersProvider configuration statusThe single source of truth for sandbox/live/unconfigured, read by the admin Providers page and `SandboxBanner`.
Auth: Public — no session or key required
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 429 | application/problem+json | Rate limited — retry after the `Retry-After` seconds. |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
10 routes
Public registry measurements. Every figure is an EvidenceValue.
/v1/registry/coverageRegistry coverage counterEvidenceValue (unit `count`, source type `internal_measurement`). Phase 0 has no providers table yet, so the value is the number of distinct publishers with a source retrieved within 30 days, read live from the database; `n` is the total number of sources.
Auth: Public — no session or key required
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 429 | application/problem+json | Rate limited — retry after the `Retry-After` seconds. |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/providersList providersPublished providers, searchable and filterable. `q` uses trigram similarity plus a substring fallback for typo tolerance.
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|
7 routes
Passkeys (WebAuthn), magic links, and sessions.
/v1/auth/passkey/register/optionsStart passkey registrationCreates an unverified account for a new email, or adds a passkey to the signed-in account. An existing account that already has a passkey or a verified email must be signed in first (prevents takeover by registering a credential on someone else's address). Exempt from `Idempotency-Key`: the WebAuthn challenge is single-use by construction.
Auth: Public — no session or key required
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| string (email) (0–254 chars) | required | — | |
| displayName | string (1–80 chars) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
8 routes
The signed-in user: profile, devices, passkeys, consent ledger.
/v1/meCurrent identityWorks with the session cookie or a Bearer API key (the key's owning user and org are returned).
Auth: Session cookie or API key
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/meUpdate profileAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
14 routes
Organizations, membership, and scoped API keys.
/v1/orgsOrganizations you belong toAuth: Session cookie
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/orgsCreate an organizationCreates the org, makes the caller its owner, and activates it on the current session. Requires `Idempotency-Key`.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
20 routes
Operator routes: providers, flags, jobs, sources, audit.
/v1/admin/providersProvider statuses and the last health checkAuth: Session cookie
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/flagsFeature flagsAuth: Session cookie
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
1 route
Public list of evidence sources with reachability.
/v1/sourcesPublic evidence sourcesEvery source the registry cites, with its canonical URL (no affiliate or tracking parameters), publisher, type, reachability, and last check time.
Auth: Public — no session or key required
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
4 routes
Agent principals, spend policies, bounties, and OAuth 2.1 client credentials (PRD §5).
/v1/oauth/tokenOAuth 2.1 client-credentials grant for agentsExchanges an agent's real API key id/secret (from POST /v1/agents) for a short-lived (1 hour) signed bearer JWT, for apps/mcp's streamable-HTTP transport specifically. Real jose HS256 signing — an unknown client_id, a wrong client_secret, or a revoked/expired key all fail with a real RFC 6749 `invalid_client` error, never a fabricated token.
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| grant_type | string | required | RFC 6749 §4.4 — only the client-credentials grant is supported. |
| client_id | string (1–200 chars) | required | The agent's apiKeys row id, or its prefix — either identifies the same key. |
| client_secret |
13 routes
Funded, Proof-gated task bounties: post, apply, accept, submit, approve, dispute (PRD §5.5).
/v1/bountiesPublic list of open bountiesAuth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| cursor | query | string | optional | — |
| limit | query | integer (1–100) | optional | — |
| country | query | string (2–2 chars) | optional | — |
| minPriceAmountMinor | query | integer (0–9007199254740991) | optional | — |
| maxPriceAmountMinor | query | integer (0–9007199254740991) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json |
1 route
Real Stripe/x402 money movements (PRD §5.6). Never a computed balance.
/v1/ledgerReal money movements the caller is a party toEvery `ledger_entries` row where the caller is the bounty's poster (directly, or via an org they belong to) or its accepted earner, newest first. Each row carries the real Stripe/x402 reference and counterparty that actually moved the money — never a computed balance. Works with the session cookie or a Bearer API key.
Auth: Session cookie or API key
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| cursor | query | string | optional | — |
| limit | query | integer (1–100) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
4 routes
Open Opportunity Rankings: quarterly reports, movers, CSV/PDF downloads (PRD §6.2).
/v1/rankingsPublished rankings report periodsEvery real, published `rankings_reports` period, newest first — backs the report index and RSS/changelog-style discovery.
Auth: Public — no session or key required
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/rankings/{period}One published rankings reportThe real, immutable snapshot for this period — `@openmoney/rankings`'s own `RankingsReport` plus its real `Mover[]` and methodology version. 404 when the period has not been published yet (a real absence, not "insufficient evidence").
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
2 routes
Downloadable, versioned registry dataset snapshots — CSV and Parquet (PRD §6.3).
/v1/datasetsAvailable dataset snapshotsEvery real, published `dataset_snapshots` row (registry CSV and Parquet exports), newest first.
Auth: Public — no session or key required
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/datasets/{id}/downloadDownload a dataset snapshot (redirect)Redirects (303) to the real file in storage for this dataset snapshot — signed URL redirect, same pattern `documents` downloads already use. 404 if the id does not exist; 503 if storage is not configured.
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id |
3 routes
/v1/applications/draftDraft a proposal/cover note from evidenced facts onlyRate-capped at 10 drafts per rolling 24h (429 with Retry-After when exceeded). Rejects a draft that doesn't reference the opportunity's title/kind. No submit endpoint exists anywhere in this API — the user copies or opens the canonical application page themselves. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| opportunityId | string (1–200 chars) | required | — |
| includeFactKeys | string (1–120 chars)[] | optional | — |
| Status | Content type | Description |
|---|---|---|
| 201 |
6 routes
/v1/orgs/{id}/usageReal usage for one org's current (or requested) billing periodSession (a member of the org) or the org's own agent key. Defaults to the current UTC calendar month. When Stripe is configured and the org's active API-key tier has a real, currently-active metered Price, every money field is populated from it; otherwise every money field is honestly `null` — real usage, no invented cost.
Auth: Session cookie or API key
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| periodStart | query | string (date-time) | optional | — |
| periodEnd | query | string (date-time) | optional | — |
| id | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json |
7 routes
/v1/discoverRanked, explainable opportunity feedRuns the caller's profile through `@openmoney/matching`'s hard filters, expected-value scoring, and diversity constraint. `showExcluded=true` includes hard-filtered items (`passesHardFilters: false`) with real reasons instead of dropping them.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| cursor | query | string | optional | — |
| limit | query | integer (1–100) | optional | — |
| sort | query | "expected_value" | "net_hourly" | "payout_speed" | "freshness" | optional | — |
| showExcluded | query | boolean | optional | — |
| workMode | query | "remote" | "onsite" | "hybrid" | optional | Where the work happens. |
| country | query | string (2–2 chars) | optional | — |
| region |
4 routes
/v1/link-submissionsQueue a link for a curator to review — no automatic fetch or analysisSession auth (so there is a real person to notify once it is reviewed). Creates a real `link_submissions` row, `status: "queued"`; nothing is fetched or analyzed at submission time. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| url | string (uri) (0–2000 chars) | required | — |
| note | string (0–500 chars) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
7 routes
/v1/admin/moderation/queueModeration queue: real reports, oldest first, with real fraud-signal contextReal `reports` rows, oldest-`createdAt`-first (mirrors `GET /v1/admin/audit`'s keyset-pagination convention, direction flipped — a moderator working the default, unfiltered view sees the oldest report first; combined with `?status=open` this literally is "oldest-open-first"). Each item carries its real `moderationDecisions` row as `decision` (null until `resolved` — a report has at most one, since `resolved`/`dismissed` are both terminal) and real, non-blocking fraud-signal context from `@openmoney/trust-safety` (`fraud-signals.ts`): the reporter's own report-submission velocity, any real duplicate-account cluster their recent `device_signals` participate in, and — only for `subjectType: "bounty"` reports — the real bounty poster's own posting velocity. None of this ever blocks or restricts anything by itself.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| cursor | query | string | optional | — |
| limit | query | integer (1–100) | optional | — |
| status | query | "open" | "queued" | "resolved" | "dismissed" | optional | — |
| subjectType | query | "provider" | "opportunity" | "bounty" | "message" | "proof_presentation" | optional |
27 routes
/v1/passport/sourcesList the caller's income sourcesAuth: Session cookie
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/sourcesCreate a manual/CSV/PDF/screenshot income sourceIdempotency-Key required. Gmail/Argyle/Pinwheel sources are created by their own connect/callback/webhook routes, not this one.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
10 routes
/v1/profileGet the caller's profile and constraintsNever 404s: a caller with no `profiles` row yet gets PRD-documented defaults (capital $0, risk tolerance conservative, payout speed "any", empty everything else).
Auth: Session cookie
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/profileUpdate the profilePartial update, PRD §4.2's field list. Creates the `profiles` row on first write. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) |
21 routes
/v1/orgs/{orgId}/proof-policiesList proof policiesAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| orgId | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/orgs/{orgId}/proof-policiesCreate a proof policy ("what we require")1 route
/v1/reportsFile a report against a real provider, opportunity, bounty, message, or Proof presentationVerifies the real subject exists first for `provider`/`opportunity`/`bounty` subjectTypes (real 404 if not — never a report against nothing); `message`/`proof_presentation` have no dedicated table in this schema yet, so those are accepted on the caller's word (see `services/moderation.ts`). Creates a real `reports` row, `status: 'open'`. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| subjectType | "provider" | "opportunity" | "bounty" | "message" | "proof_presentation" | required | — |
| subjectId | string (1–200 chars) | required | — |
| category | string (1–100 chars) | required |
1 route
/v1/transparencyPublished monthly transparency countsEvery real, published `transparency_counts_snapshots` row, newest period first — real counts only, no live-computed numbers mixed in with historical ones (`apps/worker/src/jobs/transparency-counts.ts` is the only writer).
Auth: Public — no session or key required
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
7 routes
/v1/watchesList the caller's watchesAuth: Session cookie
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/watchesWatch an opportunity, provider, or saved searchExactly one of `opportunityId`/`providerId`/`searchQuery` must be present, matching `subjectType`. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| q | query | string (1–200 chars) | optional | — |
| category | query | "rideshare" | "delivery" | "local_shifts" | "home_services" | "care" | "freelance" | "ai_training" | "microtask" | "research" | "selling" | "leasing" | "tutoring" | "creator" | "agent_bounty" | "open_source" | "other" | optional | Registry category. |
| kind | query | "platform_gig" | "freelance_marketplace" | "ai_training" | "local_shift" | "selling" | "leasing" | "research_study" | "agent_bounty" | "employer_posting" | "open_source_bounty" | optional | What kind of earning this is. |
| country | query | string (2–2 chars) | optional | — |
| status | query | "published" | optional | — |
| cursor | query | string | optional | — |
| limit | query | integer (1–100) | optional | — |
| sort | query | "composite_desc" | "composite_asc" | "updated_desc" | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/providers/{id}Get a providerFull provider record, shaped to round-trip through `@openmoney/schema`'s `Provider` type. 404 when unpublished or missing.
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (1–200 chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/providers/{id}/scorecardGet a provider's scorecardLatest scorecard for the provider's primary opportunity (the earliest-published one), or for `?opportunityId=` when given.
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| opportunityId | query | string (1–200 chars) | optional | — |
| id | path | string (1–200 chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/opportunitiesList / search opportunitiesPublished opportunities, searchable and filterable. `q` uses trigram similarity over `title` (typo-tolerant) plus a substring match over `description`. Public and unauthenticated by default; also accepts a real `X-PAYMENT` header (x402, PRD §5.3) as an alternative, keyless access path for agents — honestly 402 while x402 is unconfigured in this environment, never a fabricated payment acceptance.
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| q | query | string (1–200 chars) | optional | — |
| kind | query | "platform_gig" | "freelance_marketplace" | "ai_training" | "local_shift" | "selling" | "leasing" | "research_study" | "agent_bounty" | "employer_posting" | "open_source_bounty" | optional | What kind of earning this is. |
| providerId | query | string (1–200 chars) | optional | — |
| country | query | string (2–2 chars) | optional | — |
| workMode | query | "remote" | "onsite" | "hybrid" | optional | Where the work happens. |
| minComposite | query | integer (0–100) | optional | — |
| maxFeesBps | query | integer (0–9007199254740991) | optional | — |
| status | query | "published" | optional | — |
| cursor | query | string | optional | — |
| limit | query | integer (1–100) | optional | — |
| sort | query | "composite_desc" | "composite_asc" | "updated_desc" | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 402 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/opportunities/{id}Get an opportunityFull opportunity record, shaped to round-trip through `@openmoney/schema`'s `Opportunity` type. 404 when unpublished or missing. Public and cross-origin: `Access-Control-Allow-Origin: *` (real e2e embedding needs this — see `packages/scorecard-embed`).
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (1–200 chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/opportunities/{id}/historyOpportunity change historyWhat changed and when: merged `record_versions` (content edits) and `scorecard_history` (recomputes), newest first.
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (1–200 chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/methodology/registryScoring methodologyGenerated directly from `@openmoney/scoring`'s `METHODOLOGY` constant: weights, per-dimension formula text, and the changelog. No database access.
Auth: Public — no session or key required
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 429 | application/problem+json | Rate limited — retry after the `Retry-After` seconds. |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/changelogRecord version history across providers and opportunitiesAppend-only history from `record_versions`, newest first. Filter with `subjectType` and/or `subjectId`.
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| cursor | query | string | optional | — |
| limit | query | integer (1–100) | optional | — |
| subjectType | query | "provider" | "opportunity" | optional | — |
| subjectId | query | string (1–200 chars) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/listings/verifyCheck a URL or raw text for real scam signals, with evidenceFetches the URL live (robots-respecting) or scans the supplied text, and runs every real scam-signature rule (`@openmoney/scoring`). A flag never exists without a matched excerpt/lookup — no flags does not mean "safe", it means the current rule set found nothing. Also accepts a real `X-PAYMENT` header (x402) as an alternative, keyless access path — honestly 402 while x402 is unconfigured in this environment.
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| url | string (uri) | optional | — |
| text | string (1–20000 chars) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 402 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/auth/passkey/register/verifyFinish passkey registrationVerifies the attestation against the stored challenge (5-minute expiry, single use), stores the credential, and starts a session when none exists. Exempt from `Idempotency-Key`: the WebAuthn challenge is single-use by construction.
Auth: Public — no session or key required
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| string (email) (0–254 chars) | required | — | |
| response | RegistrationResponseInput | required | — |
| nickname | string (1–60 chars) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/auth/passkey/login/optionsStart passkey sign-inWith an email, lists that account's credentials in `allowCredentials`; without one (or for an unknown/passkey-less email) returns discoverable-credential options, so the response never reveals whether an email exists. Exempt from `Idempotency-Key`: the WebAuthn challenge is single-use by construction.
Auth: Public — no session or key required
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| string (email) (0–254 chars) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/auth/passkey/login/verifyFinish passkey sign-inVerifies the assertion, updates the signature counter, and sets the session cookie. Exempt from `Idempotency-Key`: the WebAuthn challenge is single-use by construction.
Auth: Public — no session or key required
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| response | AuthenticationResponseInput | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/auth/magic-linkEmail a sign-in linkAlways responds 202 without revealing whether the address has an account. `provider` is `sandbox` (Mailpit), `live` (SMTP), or `unconfigured` (nothing was sent; the UI shows how to connect email). The link is single-use and expires in 15 minutes. Requires `Idempotency-Key`.
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| string (email) (0–254 chars) | required | — | |
| redirectTo | string (0–512 chars) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 202 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/auth/magic-link/consumeConsume a sign-in linkMarks the link used, verifies the email, starts a session, and redirects (303) to `APP_WEB_ORIGIN + redirectTo` (default `/app`). Invalid or reused links redirect to `/sign-in?error=magic-link-invalid`. GET routes are never subject to `Idempotency-Key`.
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| token | query | string (16–256 chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 303 | — | Redirect to the web app |
| 400 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/auth/logoutSign outRevokes the current session and clears the cookie. Requires `Idempotency-Key`.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 204 | — | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| displayName | string (1–80 chars) | optional | — |
| handle | string | optional | — |
| locale | string | optional | — |
| timezone | string | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/me/sessionsDevice listAuth: Session cookie
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/me/sessions/{id}Sign out a deviceAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 204 | — | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/me/passkeysPasskeys on this accountAuth: Session cookie
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/me/passkeys/{id}Rename a passkeyAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| nickname | string (1–60 chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/me/passkeys/{id}Delete a passkeyRefused (409 `last-credential`) when it is the only passkey and the email is not verified, because the account would become unreachable.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 204 | — | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/me/consentConsent ledgerEvery data access, import, share, verification, and export, newest first. Pass `cursor` from the previous page.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| cursor | query | string | optional | — |
| limit | query | integer (1–100) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| name | string (2–80 chars) | required | — |
| kind | "relying_party" | "agent_operator" | "employer" | optional | — |
| website | string (uri) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/orgs/{id}/activateSwitch the active organizationRequires `Idempotency-Key`.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/orgs/{id}/request-verificationRequest business verificationMoves the organization from `unverified` to `pending` manual review. Stripe Identity's business-verification flow is not configured yet (no `STRIPE_SECRET_KEY`), so review is done by a human, not issued instantly — this route never sets `verified` itself. Idempotent: calling again while already `pending`/`verified`/`rejected` just returns the current state. Requires `Idempotency-Key`.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/orgs/{id}/api-keysAPI keys for an organizationAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/orgs/{id}/api-keysCreate an API keyThe full key is returned once and stored only as a SHA-256 hash. Prefix is `om_live_` in production and `om_test_` elsewhere. Writes a `share:api_key` consent event for the creator. Requires `Idempotency-Key`.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| name | string (1–80 chars) | required | — |
| scopes | "me:read" | "registry:read" | "sources:read" | "proof:verify" | "proof:request" | "bounties:write" | "agents:write"[] | required | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/orgs/{id}/api-keys/{keyId}Revoke an API keyRequires `Idempotency-Key`.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| keyId | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 204 | — | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/orgs/{id}/auditAudit log for an organizationThe organization's own audit trail (org, API key, webhook, policy, and Proof-request changes) — owner/admin only, keyset-paginated newest first. Never includes `ipHash`.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| cursor | query | string | optional | — |
| limit | query | integer (1–100) | optional | — |
| action | query | string (0–100 chars) | optional | — |
| id | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/orgs/{orgId}/proof-policiesList proof policiesAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| orgId | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/orgs/{orgId}/proof-policiesCreate a proof policy ("what we require")Requires `Idempotency-Key`.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| orgId | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| name | string (1–120 chars) | required | — |
| requirements | object[] | required | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/orgs/{orgId}/webhooksList webhook endpoints (never returns signingSecret again)Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| orgId | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/orgs/{orgId}/webhooksCreate a webhook endpointGenerates and returns `signingSecret` ONCE — never retrievable again, same convention as an API key's raw value. Requires `Idempotency-Key`.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| orgId | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| url | string (uri) | required | — |
| events | "proof.verified" | "proof.revoked" | "proof.expired"[] | required | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/orgs/{orgId}/webhooks/{id}/deliveriesRecent deliveries for one webhook endpoint (audit/debugging)Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| limit | query | integer (1–200) | optional | — |
| orgId | path | string (uuid) | required | — |
| id | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/orgs/{orgId}/proof-verificationsThe org's own proof_verification_events (usage dashboard)Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| cursor | query | string | optional | — |
| limit | query | integer (1–100) | optional | — |
| orgId | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| application/problem+json |
| Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/flags/{key}Update a feature flagRequires `Idempotency-Key`. Writes before/after to the audit log.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| key | path | string (1–100 chars) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| enabled | boolean | optional | — |
| rolloutPercent | integer (0–100) | optional | — |
| audience | object | optional | — |
| description | string (1–500 chars) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/jobsQueues and recent job runsLive BullMQ counts per queue plus the last 50 `jobs_log` rows written by the worker.
Auth: Session cookie
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/jobs/link-checkEnqueue a link-check runAdds a `link-check.run` job (payload validated by `linkCheckJobSchema`) with id `link-check-<uuid>` (BullMQ forbids `:` in custom ids). Requires `Idempotency-Key`.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| sourceIds | string (uuid)[] | optional | — |
| limit | integer (−∞–5000) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 202 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/jobs/rankings-reportEnqueue a rankings-report runAdds a `rankings-report.run` job (PRD §6.2) with id `rankings-report-<uuid>`, for demoing the quarterly report without waiting a quarter. `period` (e.g. "2026-q3") defaults to the real current quarter; the job is a real no-op if that period is already published. Requires `Idempotency-Key`.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| period | string | optional | — |
| Status | Content type | Description |
|---|---|---|
| 202 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/jobs/dataset-snapshotEnqueue a dataset-snapshot runAdds a `dataset-snapshot.run` job (PRD §6.3) with id `dataset-snapshot-<uuid>`, for demoing without waiting for the real weekly schedule. No parameters — always exports the currently-published registry. Requires `Idempotency-Key`.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 202 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/jobs/data-retentionEnqueue a data-retention sweep runAdds a `data-retention.run` job (PRD §7.3) with id `data-retention-<uuid>`, for demoing the nightly privacy-retention sweep without waiting for the real schedule. No parameters — every documented table's own real retention cutoff (`apps/worker/src/jobs/data-retention.ts`) is evaluated against the real clock each run. Requires `Idempotency-Key`.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 202 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/jobs/transparency-countsEnqueue a transparency-counts runAdds a `transparency-counts.run` job (PRD §7.2) with id `transparency-counts-<uuid>`, for demoing the monthly transparency-counts publication without waiting for the real schedule. `period` (e.g. "2026-08") defaults to the real current month; the job is a real no-op if that period is already published. Requires `Idempotency-Key`.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| period | string | optional | — |
| Status | Content type | Description |
|---|---|---|
| 202 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/jobs/{id}One job: queue state plus its log rowsAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (1–200 chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/sourcesSources with reachability and last checkAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| status | query | "unchecked" | "ok" | "redirected" | "unreachable" | "changed" | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/auditAudit logAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| cursor | query | string | optional | — |
| limit | query | integer (1–100) | optional | — |
| action | query | string (0–100 chars) | optional | — |
| actorUserId | query | string (uuid) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/registry/providersCreate a draft provider, optionally fetching its known policy pagesRuns the curator fetch step against any `urls` supplied and writes the provider/opportunity rows via the same writer the pipeline and confirm route use (with no facts yet, since nothing has been extracted). Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| domain | string (3–255 chars) | required | Canonical registrable domain, e.g. "example.com". |
| brandName | string (1–200 chars) | required | — |
| legalName | string (1–200 chars) | optional | Defaults to `brandName` when omitted; a curator confirms the real legal name once the terms page is extracted. |
| otherDomains | string (1–∞ chars)[] | optional | — |
| hq | object | null | optional | — |
| jurisdictions | string (1–∞ chars)[] | optional | — |
| kinds | "platform_gig" | "freelance_marketplace" | "ai_training" | "local_shift" | "selling" | "leasing" | "research_study" | "agent_bounty" | "employer_posting" | "open_source_bounty"[] | optional | — |
| categories | string (1–∞ chars)[] | optional | — |
| urls | object | optional | Known policy-page URLs (`docs/registry/provider-sources.json` shape). Every URL supplied here is fetched immediately. |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/registry/providers/{id}/fetchRe-fetch a provider's known URLs, snapshot each, and update sourcesUses the cached curator session for this provider when present (from `POST /providers` or a prior `/fetch`); otherwise reconstructs known URLs from `termsUrl`/`payoutPolicyUrl`/`deactivationPolicyUrl` on the provider row. Pass `urls` in the body to add or override slots (needed for `fees`/`payDisclosure` once the cache has expired, since those are not stored as columns). Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (1–200 chars) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| urls | object | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/registry/providers/{id}/extractRun LLM structured extraction over the freshest fetched pagesProposes field values with `confidence` and `corroborated` (ADR-007: a value earns `high`/`corroborated: true` only by appearing, normalized, in the real fetched page text) — nothing is written yet. Requires `POST .../fetch` to have run first in this session. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (1–200 chars) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/registry/providers/{id}/confirmAccept or reject proposed fields; write the accepted onesBody `{ fields: [{ path, accept }] }`. Writes accepted fields via the same writer the automated pipeline uses; rejected fields are dropped. Requires `POST .../extract` to have run first in this session. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (1–200 chars) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| fields | object[] | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/registry/providers/{id}/publishPublish a provider once it clears the evidence barRefuses (409) unless the provider has at least 3 distinct sources and one corroborated fee or payout fact. On success, bumps `version`, snapshots `record_versions`, and recomputes every opportunity's scorecard. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (1–200 chars) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/registry/opportunities/{id}/recomputeRecompute one opportunity's scorecard from current DB factsAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (1–200 chars) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/registry/queueFreshness and confirmation queueEvery opportunity, flagged `stale` (`lastVerifiedAt` null or older than 30 days) and `needsConfirmation` (provider not yet `published` — the closest DB-backed proxy for "has fields a curator has not confirmed"), stale-and-unconfirmed first.
Auth: Session cookie
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/registry/providers/{id}Full provider record for curator review, including pending proposed fieldsAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (1–200 chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| string (1–500 chars) |
| required |
| The raw API key the caller received once from POST /v1/agents. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Rate limited — retry after the `Retry-After` seconds. |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/agentsRegister an agent under the caller (or their active agent_operator org)Principal is the caller's session, or their active organization when it is an `agent_operator` org (same 'active org' convention as `POST /v1/orgs/{id}/api-keys`) — never any other org kind. `id` is the supplied `didKey`, or a generated `agent_<uuid>`. Creates a real `apiKeys` row (scopes `agents:write`, `bounties:write`, `proof:verify`) and returns the raw key **once** — store it now, it is never retrievable again. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| name | string (1–120 chars) | required | — |
| didKey | string (1–500 chars) | optional | A did:key the caller generated client-side. Omit for a platform-issued id (agent_<uuid>). |
| policy | AgentPolicyBodyInput | required | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/agents/{id}/policyThe agent's own spend policyReadable by the agent's own API key, or by its principal (session).
Auth: Session cookie or API key
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (1–200 chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/agents/{id}/policyUpdate the agent's spend policyPrincipal-only (owner/admin of the principal org, or the principal user) — never the agent's own key, so an agent can never raise its own spending limit. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (1–200 chars) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| maxPerBountyAmountMinor | integer (−∞–9007199254740991) | optional | — |
| maxPerBountyCurrency | string | optional | ISO 4217 currency code, e.g. USD, INR. |
| maxPerDayAmountMinor | integer (−∞–9007199254740991) | optional | — |
| maxPerDayCurrency | string | optional | ISO 4217 currency code, e.g. USD, INR. |
| allowedKinds | "platform_gig" | "freelance_marketplace" | "ai_training" | "local_shift" | "selling" | "leasing" | "research_study" | "agent_bounty" | "employer_posting" | "open_source_bounty"[] | optional | — |
| allowedCountries | string (2–2 chars)[] | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/bountiesPost a bounty (real content-rule check; blocked bounties are recorded, not silently dropped)Caller is a signed-in principal (web) or an agent API key (`bounties:write` scope). An agent-posted bounty additionally requires a body `mandate`, verified via a real ES256 JWS check and checked against the real trailing-24h spend policy — a failed mandate or policy check 403s with the real reason, no row written. On success, `checkBountyContent` always runs; any real violation 403s with the rule code(s) cited and the bounty is still created (`status: 'cancelled'`) with the result attached for audit. A clean bounty is created `pending_funding`, ready to fund. Idempotency-Key required.
Auth: Session cookie or API key
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| title | string (4–200 chars) | required | — |
| taskSpec | string (10–10000 chars) | required | — |
| deliverableSpec | string (4–2000 chars) | required | — |
| remote | boolean | optional | — |
| geoCountries | string (2–2 chars)[] | optional | — |
| geoCities | string (1–120 chars)[] | optional | — |
| deadline | string (date-time) | optional | — |
| priceAmountMinor | integer (−∞–9007199254740991) | required | — |
| priceCurrency | string | required | ISO 4217 currency code, e.g. USD, INR. |
| requiredProofPolicy | object[] | optional | — |
| maxApplicants | integer (−∞–500) | optional | — |
| mandate | MandateBodyInput | optional | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/bounties/{id}/fundFund a bounty (pending_funding -> funded -> open)Real Stripe PaymentIntent (manual capture, captured immediately) or an x402 funding intent, per `rail`. Honestly blocked (503 `stripe-unconfigured`/`x402-unconfigured`) while credentials are unset — the one real funding boundary this environment cannot cross. On real success: a real `ledger_entries` row (`kind: 'fund'`), then `funded -> open` in the same call. Poster/principal only. Idempotency-Key required.
Auth: Session cookie or API key
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| rail | "stripe" | "x402" | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 503 | application/problem+json | Default Response |
/v1/bounties/{id}Bounty detail — public for open/accepted/submitted, full for the poster/principalAuth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/bounties/{id}/applicantsApplicants for one bounty — poster/principal onlyAuth: Session cookie or API key
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/bounties/{id}/applyApply with real Proof shares satisfying requiredProofPolicyVerifies each real `proof_shares` row (ownership, non-revoked, matching type/freshness) against `requiredProofPolicy` before writing. `maxApplicants` enforced. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| proofShareIds | string (uuid)[] | optional | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/bounties/{id}/acceptAccept one applicant, reject the rest (open -> accepted). Poster/principal only.Auth: Session cookie or API key
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| applicationId | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/bounties/{id}/submissionsSubmit deliverables (accepted -> submitted). The accepted earner only.Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| deliverables | object[] | required | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/bounties/{id}/submissions/{sid}/approveApprove a submission (submitted -> approved), then release funds (approved -> released)Poster/principal only. Marks the deliverable approved for real, then attempts the real release (Stripe capture+transfer, or x402) — honestly blocked (503) while unconfigured, in which case the bounty is left `approved` (accepted, payout pending real credentials), never silently stuck at `submitted`. On real success: two `ledger_entries` rows (`release` to the earner, `fee` to the platform). Idempotency-Key required.
Auth: Session cookie or API key
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| sid | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 503 | application/problem+json | Default Response |
/v1/bounties/{id}/disputesOpen a dispute (submitted -> disputed). Either side — a human principal via session, or an agent (whose API key resolves to its principal) via Bearer.Auth: Session cookie or API key
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| submissionId | string (uuid) | required | — |
| reason | string (4–2000 chars) | required | — |
| evidence | object[] | optional | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/bounties/{id}/cancelCancel a bounty. Poster/principal only, only from a cancellable state. Refunds if already funded.Auth: Session cookie or API key
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 503 | application/problem+json | Default Response |
/v1/admin/disputesCurator/admin dispute-review queueEvery dispute joined with its bounty title/price, newest first. `status` narrows to open/resolved; omitted returns every dispute.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| status | query | "open" | "resolved" | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/disputes/{id}/resolveCurator/admin resolves a dispute: release, partial, or refundReal Stripe refund/release call per outcome — honestly blocked (503) while unconfigured. Writes the real ledger_entries row(s). Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| outcome | "release" | "partial" | "refund" | required | — |
| outcomeAmountMinor | integer (−∞–9007199254740991) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 503 | application/problem+json | Default Response |
| period |
| path |
| string |
| required |
| — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/rankings/{period}.csvRankings report CSV (redirect)Redirects to the real, already-generated CSV for this period (`rankings_reports.csvDocumentId`) — the same file the worker job rendered, byte-identical on every download. 404 if no report has been published for this period; 503 if storage is not configured.
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| period | path | string | required | — |
| Status | Content type | Description |
|---|---|---|
| 303 | — | Redirect to the real file in storage |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 503 | application/problem+json | Default Response |
/v1/rankings/{period}.pdfRankings report PDF (redirect)Redirects to the real, already-generated PDF for this period (`rankings_reports.pdfDocumentId`), never generated on request. 404 if no report has been published for this period; 503 if storage is not configured.
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| period | path | string | required | — |
| Status | Content type | Description |
|---|---|---|
| 303 | — | Redirect to the real file in storage |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 503 | application/problem+json | Default Response |
| path |
| string (uuid) |
| required |
| — |
| Status | Content type | Description |
|---|---|---|
| 303 | — | Redirect to the real file in storage |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 503 | application/problem+json | Default Response |
| application/json |
| Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/applications/draftsList the caller's draftsAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| opportunityId | query | string (1–200 chars) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/applications/{opportunityId}/outcomeReport an outcome for an opportunity you applied to`sharedToRegistry` defaults `false` — explicit opt-in. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| opportunityId | path | string (1–200 chars) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| status | "applied" | "accepted" | "rejected" | "paid" | "scammed" | required | — |
| draftId | string (uuid) | optional | — |
| note | string (0–2000 chars) | optional | — |
| sharedToRegistry | boolean | optional | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/billing/pricingReal Stripe Prices/Products for the public pricing pageHonestly `stripe-unconfigured` (503) when no Stripe key exists in this environment — the pricing page renders that state, never invented numbers.
Auth: Public — no session or key required
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 503 | application/problem+json | Default Response |
/v1/billing/subscriptionThe signed-in user's own Earner Plus subscriptionTheir most recent real `subscriptions` row, whatever its status — `null` when they have never subscribed. Earner Plus is always per-user (never org-billed); this never reads another user's row.
Auth: Session cookie
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/billing/checkoutReal Stripe Checkout Session URL for Earner Plus`priceId` must be one of the real, currently-active ids `GET /v1/billing/pricing` just listed — any other id, even syntactically valid, is rejected so a client can never charge an arbitrary Stripe price. Creates/reuses the caller's `stripe_customers` row. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| priceId | string (1–∞ chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 503 | application/problem+json | Default Response |
/v1/billing/portalReal Stripe Customer Portal URL — the one-click-cancel channelRequires an existing `stripe_customers` row (subscribe via POST /v1/billing/checkout first). Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 503 | application/problem+json | Default Response |
/v1/billing/webhookReal Stripe Billing webhook receiver (distinct signing secret from Connect's webhook)Verifies the real signature against STRIPE_BILLING_WEBHOOK_SECRET, then for each of SUBSCRIPTION_CONFIRMATION_EVENTS sends the real confirmation email and upserts subscriptions/stripe_customers, validating every status write through assertTransition first. An illegal transition is logged and rejected with 500 so Stripe retries — never silently applied.
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Rate limited — retry after the `Retry-After` seconds. |
| 500 | application/problem+json | Default Response |
| 503 | application/problem+json | Default Response |
| query |
| string (1–120 chars) |
| optional |
| — |
| riskTolerance | query | "conservative" | "moderate" | "aggressive" | optional | — |
| payoutSpeedNeeded | query | "same_day" | "weekly" | "monthly" | "any" | optional | — |
| minAcceptableNetHourlyAmountMinor | query | integer (0–9007199254740991) | optional | — |
| hoursPerWeek | query | integer (0–168) | optional | — |
| capitalAvailableAmountMinor | query | integer (0–9007199254740991) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/discover/{id}One opportunity's full match explanation plus its registry recordAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (1–200 chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/discover/{id}/similarSimilar opportunities (same kind), ranked the same way as the feedAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (1–200 chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/discover/{id}/saveSave an opportunityIdempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (1–200 chars) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 204 | — | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/discover/{id}/saveRemove a saveAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (1–200 chars) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 204 | — | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/discover/{id}/hideHide an opportunity, with an optional reasonIdempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (1–200 chars) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| reason | string (0–500 chars) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 204 | — | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/discover/{id}/hideUn-hide an opportunityAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (1–200 chars) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 204 | — | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 400 |
| application/problem+json |
| Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/link-submissionsEvery real link submission, oldest firstSame keyset-pagination convention as `GET /v1/admin/appeals` and `GET /v1/admin/moderation/queue`.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| cursor | query | string | optional | — |
| limit | query | integer (1–100) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/link-submissions/{id}/reviewMark a link submission reviewed (queued -> reviewed)Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/link-submissions/{id}/dismissDismiss a link submission — no action warrantedAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/moderation/{reportId}/queuePick up a report for review (open -> queued)Real `open -> queued` transition via `@openmoney/trust-safety`'s `assertTransition`. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| reportId | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/moderation/{reportId}/decideRecord a real human moderation decision (queued -> resolved)Writes a real `moderation_decisions` row with `reviewerUserId: req.auth.user.id` — `assertHumanReviewed` runs before the insert (defense-in-depth alongside the schema's own `NOT NULL`; PRD §7.2's adverse-action rule: every decision here is a real, attributed human judgment, never automated). Real `queued -> resolved` transition. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| reportId | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| decision | "no_action" | "warn" | "restrict" | "remove" | required | — |
| templatedReason | string (1–2000 chars) | required | — |
| evidence | ModerationEvidenceItemInput[] | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/moderation/{reportId}/dismissDismiss a report — no action warranted (open|queued -> dismissed)Real `open|queued -> dismissed` transition. The real dismissal reason is written to the audit log's own `reason` field (`reports` has no separate reason column). Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| reportId | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| reason | string (1–2000 chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/moderation/{decisionId}/appealAppeal a real moderation decision — the decision's report's reporter, the bounty's real principal (when the decision's report targeted a bounty), or an admin/curatorSession auth. Who may appeal is deliberately scoped to what this schema can really verify: the report's own `reporterUserId`, the real principal of the bounty when `subjectType` is `"bounty"` (`bountyPostedByPrincipal`, reused from `services/settlement.ts`), or an admin/curator acting on someone's behalf — a provider/opportunity/message/proof_presentation report has no single real per-user owner in this schema to check against. Creates a real `appeals` row, `appellantUserId: req.auth.user.id`. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| decisionId | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| reason | string (4–2000 chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/appealsAppeals queue: every real appeal, oldest firstReal `appeals` rows, oldest-`createdAt`-first (same keyset-pagination convention as `GET /v1/admin/moderation/queue` and `GET /v1/admin/audit`). Documented gap: `docs/api/phase-7-contract.md` only spells out `POST /v1/admin/appeals/{appealId}/resolve`, not this listing route — added because `apps/web`'s admin/curator appeals queue (`AppealsQueue.tsx`) needs a real list to resolve against and none existed.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| cursor | query | string | optional | — |
| limit | query | integer (1–100) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/admin/appeals/{appealId}/resolveResolve an appeal with a real, different reviewerReal `assertAppealReviewerDiffers` check before writing — a real 403 (`appeal-same-reviewer`) if the caller made the original decision (PRD §7.2: "appeals with a different reviewer"). The resolver's own rationale (`reason`) is written to the audit log, alongside the appellant's original `appeals.reason`, which is left untouched. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| appealId | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| outcome | "upheld" | "overturned" | "partial" | required | — |
| reason | string (1–2000 chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| providerId | string (1–200 chars) | optional | — |
| providerLabel | string (1–200 chars) | required | — |
| connectionType | "csv" | "pdf" | "screenshot" | "manual" | required | Sources created directly by the caller; email/argyle/pinwheel sources are created by their own connect/callback/webhook routes. |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/sources/{id}Disconnect a sourceSets status to `disconnected`; does not delete its earnings_events (use Settings -> Data delete for that).
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 204 | — | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/sources/{id}/import/csvImport a CSV/XLSX statement, or confirm a low-confidence column mappingTwo call shapes: a multipart upload (field `file`) to parse a new statement, or a JSON body `{ documentId, mapping, model, promptVersion }` (the exact values a prior low-confidence response returned) to apply a human-reviewed mapping with no further LLM call. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 415 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/sources/{id}/import/pdfImport a PDF statement (multipart upload)Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 415 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/sources/{id}/import/screenshotImport a screenshot/photo of a statement (multipart upload)Strips EXIF, runs vision extraction, and a real error-level-analysis edited-image heuristic. Always writes confirmedByUser: false, extractionConfidence <= 0.6 (PRD §2.3).
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 415 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/sources/gmail/connectStart the Gmail OAuth flow (gmail.readonly, label-scoped)503 with `{ integration: "google", mode: "unconfigured", howTo }` when GOOGLE_CLIENT_ID/SECRET are not set — never a fabricated authorization URL.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 503 | application/problem+json | Default Response |
/v1/passport/sources/gmail/callbackOAuth redirect targetOn success creates an income_sources row (connectionType: email) and a consent_events row (scope: import:gmail), then redirects back to the app.
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| code | query | string | optional | — |
| state | query | string | optional | — |
| error | query | string | optional | — |
| Status | Content type | Description |
|---|---|---|
| 303 | — | Default Response |
| 400 | application/problem+json | Default Response |
| 429 | application/problem+json | Rate limited — retry after the `Retry-After` seconds. |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 503 | application/problem+json | Default Response |
/v1/passport/sources/argyle/connectCreate a real Argyle sandbox user and Link token503 with `{ integration: "argyle", mode: "unconfigured", howTo }` when ARGYLE_CLIENT_ID/SECRET are not set.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 503 | application/problem+json | Default Response |
/v1/passport/sources/argyle/webhookReal Argyle webhook receiver (HMAC-SHA512 signature-verified)Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Rate limited — retry after the `Retry-After` seconds. |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 503 | application/problem+json | Default Response |
/v1/passport/sources/pinwheel/connectCreate a real Pinwheel sandbox Link token503 with `{ integration: "pinwheel", mode: "unconfigured", howTo }` when PINWHEEL_API_SECRET is not set.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 503 | application/problem+json | Default Response |
/v1/passport/sources/pinwheel/webhookReal Pinwheel webhook receiver (HMAC-SHA256 signature-verified)Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Rate limited — retry after the `Retry-After` seconds. |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 503 | application/problem+json | Default Response |
/v1/passport/eventsList the caller's earnings_eventsAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| providerId | query | string (1–200 chars) | optional | — |
| incomeSourceId | query | string (uuid) | optional | — |
| from | query | string (date-time) | optional | — |
| to | query | string (date-time) | optional | — |
| needsConfirmation | query | boolean | optional | — |
| cursor | query | string | optional | — |
| limit | query | integer (1–200) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/events/export.csvStream the caller's full ledger as CSVAuth: Session cookie
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/events/{id}Full row including a signed URL to the source documentAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/events/{id}Edit or confirm one earnings eventAny editable field subset plus `confirm`. Any successful call always sets confirmedByUser: true and extractionConfidence: null — a human correction is not a model confidence.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| occurredAt | string (date-time) | optional | — |
| periodStart | string (date-time) | null | optional | — |
| periodEnd | string (date-time) | null | optional | — |
| currency | string | optional | ISO 4217 currency code, e.g. USD, INR. |
| grossAmountMinor | integer (-9007199254740991–9007199254740991) | optional | — |
| tipsAmountMinor | integer (-9007199254740991–9007199254740991) | optional | — |
| platformFeesAmountMinor | integer (-9007199254740991–9007199254740991) | optional | — |
| otherFeesAmountMinor | integer (-9007199254740991–9007199254740991) | optional | — |
| reimbursementsAmountMinor | integer (-9007199254740991–9007199254740991) | optional | — |
| hoursActive | number | null | optional | — |
| hoursOnline | number | null | optional | — |
| tasks | integer (-9007199254740991–9007199254740991) | null | optional | — |
| miles | number | null | optional | — |
| confirm | boolean | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/events/{id}Remove a single wrongly-imported rowAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 204 | — | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/analytics/overviewLive analytics over the caller's earnings_eventsRuns @openmoney/scoring's passport engine live (never a cached row) — always current.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| window | query | "7d" | "30d" | "90d" | "12m" | optional | — |
| providerId | query | string (1–200 chars) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/analytics/by-platformOne PassportAnalytics per provider the caller has events forAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| window | query | "7d" | "30d" | "90d" | "12m" | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/analytics/counterfactualThe caller's own net-hourly p50 against the registry's published evidence for the same providerAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| providerId | query | string (1–200 chars) | required | — |
| window | query | "7d" | "30d" | "90d" | "12m" | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/analytics/refreshAdmin/worker-triggered: recompute and upsert derived_metrics for one userNot user-facing — the nightly aggregation job calls this so it has a stable snapshot instead of recomputing every user live.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| userId | query | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/exportEnqueue a zip export (JSON + CSV + original documents)Idempotency-Key required. The worker (apps/worker/src/jobs/passport-export.ts) processes the job and marks the row ready with a signed download URL.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 202 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/export/{id}Poll export statusAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/deleteStart the two-step deletion of every Passport row and stored document for the callerBody `confirmationPhrase` must equal the caller's account email (first factor). Idempotency-Key required. Sends a single-use confirmation link to that email (second factor, PRD §2.5) and returns its request id immediately; nothing is deleted, and the worker job (apps/worker/src/jobs/passport-delete.ts) is not enqueued, until POST /v1/passport/delete/confirm consumes that link.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| confirmationPhrase | string (1–320 chars) | required | Must equal the caller's account email, checked server-side. |
| Status | Content type | Description |
|---|---|---|
| 202 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/delete/confirmConsume a Passport-deletion confirmation link and enqueue the real delete jobNo session required, same as GET /v1/auth/magic-link/consume — the single-use token from the confirmation email is itself the proof, since the email may be opened on a device that never had a session here. Only on `status: "deleted"` is apps/worker/src/jobs/passport-delete.ts actually enqueued.
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| token | string (1–∞ chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/consent-logThe caller's consent_events rowsAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| cursor | query | string | optional | — |
| limit | query | integer (1–100) | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/passport/consent/aggregateToggle the aggregate:anonymized consent scope (default off)Gates whether the nightly aggregation job (apps/worker/src/jobs/passport-aggregate.ts) may include this user's data. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| optIn | boolean | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| optional |
| UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| locationCountry | string (2–2 chars) | null | optional | — |
| locationRegion | string (1–120 chars) | null | optional | — |
| locationCity | string (1–120 chars) | null | optional | — |
| workModes | "remote" | "onsite" | "hybrid"[] | optional | — |
| hoursPerWeek | integer (0–168) | null | optional | — |
| timeWindows | object[] | optional | — |
| hasVehicle | boolean | null | optional | — |
| equipment | string (1–80 chars)[] | optional | — |
| credentialsHeld | string (1–80 chars)[] | optional | — |
| backgroundCheckWilling | boolean | null | optional | — |
| minAcceptableNetHourlyAmountMinor | integer (0–9007199254740991) | null | optional | — |
| minAcceptableNetHourlyCurrency | string | null | optional | — |
| payoutSpeedNeeded | "same_day" | "weekly" | "monthly" | "any" | optional | — |
| capitalAvailableAmountMinor | integer (0–9007199254740991) | optional | — |
| capitalAvailableCurrency | string | optional | ISO 4217 currency code, e.g. USD, INR. |
| riskTolerance | "conservative" | "moderate" | "aggressive" | optional | — |
| jurisdictions | string (2–2 chars)[] | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/profile/skillsList typed and Passport-inferred skillsAuth: Session cookie
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/profile/skillsAdd a typed skillThe user typed this themselves, so it is confirmed immediately (`source: "typed"`, `confirmed: true`). Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| label | string (1–120 chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/profile/skills/inferInfer skills from confirmed Passport earningsReads confirmed `earnings_events`, maps each provider to its registry `categories[]`, and inserts any not already present as `source: "passport_inferred"`, `confirmed: false`. Idempotent by `(userId, label)` — safe to call repeatedly. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/profile/skills/{id}/confirmConfirm a skillNever auto-confirmed anywhere else. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/profile/skills/{id}Dismiss a skill (typed or inferred)Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 204 | — | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/profile/interestsList interest tagsAuth: Session cookie
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/profile/interestsAdd an interest tagFree text, never a protected characteristic (PRD §4.3's fairness control). Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| tag | string (1–80 chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/profile/interests/{id}Remove an interest tagAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 204 | — | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
Requires `Idempotency-Key`.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| orgId | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| name | string (1–120 chars) | required | — |
| requirements | object[] | required | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/orgs/{orgId}/webhooksList webhook endpoints (never returns signingSecret again)Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| orgId | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/orgs/{orgId}/webhooksCreate a webhook endpointGenerates and returns `signingSecret` ONCE — never retrievable again, same convention as an API key's raw value. Requires `Idempotency-Key`.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| orgId | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| url | string (uri) | required | — |
| events | "proof.verified" | "proof.revoked" | "proof.expired"[] | required | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/orgs/{orgId}/webhooks/{id}/deliveriesRecent deliveries for one webhook endpoint (audit/debugging)Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| limit | query | integer (1–200) | optional | — |
| orgId | path | string (uuid) | required | — |
| id | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/orgs/{orgId}/proof-verificationsThe org's own proof_verification_events (usage dashboard)Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| cursor | query | string | optional | — |
| limit | query | integer (1–100) | optional | — |
| orgId | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/proofsList the caller's issued proofsNo `sdJwt` in the list view — fetch GET /v1/proofs/{id} for the full credential.
Auth: Session cookie
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/proofsIssue a new Proof from real Passport/registry/identity dataRuns the matching claim computer (`@openmoney/proof`'s claims/*). 409 `insufficient-evidence` when it finds no real evidence to issue this type honestly; 409 `holder-key-required` when the caller has not registered a holder public key yet (`POST /v1/proofs/holder-key` first); 503 when the type needs an integration that is not configured in this environment (identity -> Stripe Identity). Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| type | "identity" | "active_earner" | "earnings" | "reliability" | "skill" | "platform_standing" | required | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| 503 | application/problem+json | Default Response |
/v1/proofs/holder-keyRegister/update the session's current holder public keyThe matching private key is generated and held entirely in the browser (WebCrypto) and never sent here (A3.4) — only its public half, embedded in every newly issued credential's `cnf` claim from now on. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| publicJwk | JwkInput | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/proofs/{id}Full record including the real, all-disclosures sdJwtOnly the owner may fetch this — it's what the browser needs to build a selective presentation locally via presentProof.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/proofs/{id}/revokeRevoke a proofFlips its Status List bit and re-signs that issuer key's Status List Token SYNCHRONOUSLY in this handler (A3.3's 60-second propagation is trivially met by not queuing this step). Enqueues real proof.revoked webhook deliveries to every org that has previously verified this proof. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 409 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/proofs/{id}/sharesCreate a share link (bookkeeping only — the presentation itself is built client-side, never uploaded)Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| audience | string (1–2000 chars) | optional | — |
| expiresInSeconds | integer (−∞–2592000) | required | — |
| disclosedClaimPaths | string (1–∞ chars)[] | required | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/proofs/shares/{id}Public metadata for a share link — never claim valuesFor a relying-party page to render "what this share claims to be" before a live verification happens.
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/proofs/{id}/verification-logThe caller's own verification events for this proof ("who verified what, when")Hash-only — never re-derives what was disclosed beyond the disclosedClaimPaths array already logged.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/proofs/verify/nonceMint a real single-use nonce a presentation request must embed (the actual replay defense, A3.3)Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| audience | string (1–2000 chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/proofs/verifyVerify a presentationRejects a nonce not found freshly un-consumed in `proof_nonces` with 400 (A3.3 replay defense — server-side tracking, not just the presentation's own internal nonce field). Writes one proof_verification_events row (hash of the presentation, never the presentation itself) regardless of outcome. When called with a proof:verify-scoped API key, enqueues real proof.verified webhook deliveries for that key's org. This is the exact route the SDK, the embeddable widget, the hosted verify page, and the console's paste-a-presentation tool all call (A3.1).
Auth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| presentation | string (1–∞ chars) | required | — |
| audience | string (1–2000 chars) | required | — |
| nonce | string (1–∞ chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/proofs/status-list/{kid}Live-built, real signed Status List Token for one issuer keyAuth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| kid | path | string (1–500 chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/proofs/requestsCreate a "request a Proof" link an earner can open and fulfilIdempotency-Key required.
Auth: API key (Bearer)
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| policyId | string (uuid) | optional | — |
| expiresInSeconds | integer (−∞–2592000) | required | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 403 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/proofs/requests/{id}Status of a request-a-Proof linkAuth: Public — no session or key required
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/.well-known/did.jsondid:web document over every issuer key this deployment has ever signed withAuth: Public — no session or key required
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/.well-known/jwks.jsonPlain JWKS — what most SD-JWT VC verifiers (including our own SDK) actually fetchAuth: Public — no session or key required
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
| — |
| detail | string (1–5000 chars) | required | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| subjectType | "opportunity" | "provider" | "search" | required | — |
| opportunityId | string (1–200 chars) | optional | — |
| providerId | string (1–200 chars) | optional | — |
| searchQuery | object | optional | — |
| channels | "web_push" | "email"[] | optional | — |
| digest | "immediate" | "daily_digest" | "weekly_digest" | optional | — |
| Status | Content type | Description |
|---|---|---|
| 201 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/watches/{id}Update channels, digest, or pause stateIdempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| channels | "web_push" | "email"[] | optional | — |
| digest | "immediate" | "daily_digest" | "weekly_digest" | optional | — |
| paused | boolean | optional | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/watches/{id}Remove a watchAuth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
| Status | Content type | Description |
|---|---|---|
| 204 | — | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/watches/{id}/eventsReal change history for a watch's subjectOpportunity/provider-type watches: real `watch_events` rows. Search-type watches: new-match history from `alert_deliveries` where `kind = "new_match"`.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
| Status | Content type | Description |
|---|---|---|
| 200 | application/json | Default Response |
| 401 | application/problem+json | Default Response |
| 404 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/push-subscriptionsRegister a Web Push subscriptionThe browser Push API's own `PushSubscriptionJSON` shape. Upserts by `endpoint`. Idempotency-Key required.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| endpoint | string (uri) | required | — |
| keys | object | required | — |
| Status | Content type | Description |
|---|---|---|
| 204 | — | Default Response |
| 400 | application/problem+json | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |
/v1/push-subscriptionsUnregister a Web Push subscriptionCalled on `pushsubscriptionchange`/unsubscribe from the client.
Auth: Session cookie
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Idempotency-Key | header | string (uuid) | optional | UUID chosen by the client. The server rejects mutating requests that omit it (400 `idempotency-key-required`); the generated SDK (@openmoney/api-client) adds one automatically, which is why it is not marked required here. The first response is stored for 24 hours and replayed for the same key with `Idempotent-Replayed: true`. |
Request body · application/json
| Field | Type | Required | Description |
|---|---|---|---|
| endpoint | string (uri) | required | — |
| Status | Content type | Description |
|---|---|---|
| 204 | — | Default Response |
| 401 | application/problem+json | Default Response |
| 429 | application/problem+json | Default Response |
| 500 | application/problem+json | Unexpected error. The `requestId` and `traceId` identify the failure in logs. |