Skip to main content
ReconLayer is built API-first. The dashboard is a consumer of this API, not the platform boundary — anything you can do in the dashboard, you can do programmatically, and the dashboard itself calls the same /v1/* routes documented here.

Route structure mirrors the domain

The API’s route groups map directly onto ReconLayer’s core domain model:
PrefixPurpose
/v1/payment-intentsExpected payments — the canonical record of what should happen for a transfer.
/v1/reconciliation-casesReconciliation truth and workflow — the matched (or unmatched) outcome for each payment intent.
/v1/evidence/*Ingest provider and on-chain evidence that the matcher reconciles against payment intents.
/v1/integrations, /v1/bridge-integrations, /v1/onchain-integrationsConnections to banking, stablecoin, and on-chain data sources.
/v1/outbound-webhook-endpoints, /v1/outbound-webhook-eventsClient callback subscriptions and delivery tracking — ReconLayer notifying you.
/webhooks/*Provider callbacks — providers notifying ReconLayer.
/v1/import-profiles, /v1/import-batchesBulk file-based ingestion of payment intents and evidence.
/v1/api-keysHeadless credential management (signed-in users only).
/webhooks/* (inbound, from providers) and /v1/outbound-webhook-* (outbound, to your systems) are deliberately separate namespaces. See Authentication for how each is secured.

Base URL and versioning

http://localhost:3001        (local development)
All resource routes are versioned under /v1. The machine-readable OpenAPI contract is served at /openapi.json and /openapi.yaml, and an interactive Scalar API explorer is available at /docs — both are public and require no credential.

Authentication model

Every /v1/* route requires a Bearer credential — either an API key (headless clients, organization and scopes are bound to the key) or a Clerk session token (dashboard users, organization resolved from the session or x-organization-id). See Authentication for the full model, including the local-only dev bypass.

Idempotency on writes

Network failures happen. If a POST to ReconLayer times out or your client crashes mid-request, you need a safe way to retry without creating a duplicate PaymentIntent, evidence record, or reconciliation side effect. Client write endpoints require an Idempotency-Key header:
  1. Generate the key before the first attempt — a UUID or other unique, stable string scoped to that logical operation.
  2. Reuse the exact same key on every retry of that same logical request.
  3. ReconLayer stores the request’s hash and result keyed by (organizationId, operation, idempotencyKey). A retry with the same key and the same body replays the original response — no new record is created, and the response carries Idempotency-Replayed: true.
  4. Reusing the key with a different request body returns 409 idempotency_key_conflict instead of executing anything.
See Idempotency for the full mechanics, including what happens to a request that is still in flight.

Business-level uniqueness

The Idempotency-Key header prevents the same request from being executed twice. ReconLayer separately enforces business-level uniqueness to prevent different requests from creating duplicate domain records. For payment intents, this is the externalReference field — your stable, internal identifier for the payment. ReconLayer deduplicates on (organizationId, externalReference):
  • Reuse — if you POST /v1/payment-intents with a new Idempotency-Key but an externalReference that already exists and the canonical fields (amounts, currencies, beneficiary, etc.) match, ReconLayer returns the existing payment intent with "outcome": "reused" and a 200 status — no duplicate is created.
  • Conflict — if the externalReference already exists but the new request’s canonical fields don’t match the stored record, ReconLayer rejects the request with 409 payment_intent_conflict and a mismatches array describing exactly which fields disagree.
  • Created — if the externalReference is new, ReconLayer creates the payment intent and its reconciliation case, returning "outcome": "created" and a 201 status.
201 Created
{
  "caseId": "case_01J...",
  "paymentIntentId": "pi_01J...",
  "externalReference": "invoice-9182",
  "status": "reconciling",
  "verdict": null,
  "outcome": "created"
}
200 Reused — already existed, fields match
{
  "caseId": "case_01J...",
  "paymentIntentId": "pi_01J...",
  "externalReference": "invoice-9182",
  "status": "reconciling",
  "verdict": null,
  "outcome": "reused"
}

Pagination

List endpoints (GET /v1/payment-intents, GET /v1/reconciliation-cases, GET /v1/api-keys, etc.) take limit and offset query parameters and return a consistent envelope:
{ "items": [ /* ... */ ], "total": 128, "limit": 25, "offset": 0 }
See Pagination for defaults, maximums, and traversal patterns.

Errors

All errors share an envelope with at minimum an error machine-readable code, usually with a message. Validation failures additionally include an issues array pinpointing the offending field. See Errors for the full catalog of codes and HTTP statuses.

Rate limits

Requests are rate-limited per organization (or per IP for unauthenticated/public traffic), with standard RateLimit-* response headers and a 429 response when exceeded. See Rate limits.

Next steps

  • Authentication — credential types and organization resolution.
  • Idempotency — the Idempotency-Key contract in depth.
  • Quickstart — create an API key and run through a full payment-intent → evidence → reconciliation flow.