POST /transactions Bearer · OAuth2 201 Created Idempotency-Key /sale · /pre-auth
Paying.co · Foundry · The API Surface · REST integration layer

The surface. One REST API
over the whole stack.

The capstone — how integrators drive Foundry. A small, clean REST surface: authenticate, then a few commands grouped by what they do — transactions, configuration, device status. The transaction set now spans sale, pre-authorization, completion, void, and refund. The surface is served by the native C engine; language wrappers expose it without reimplementing the logic. Offline store-and-forward is a named later phase, not this iteration.

status shipped REST · JSON OAuth2 Bearer sale · pre-auth · completion · void · refund
Where it sits · the outermost layer

The API is the public face of everything docs 01–06 built. It exposes the semi-integrated interface (doc 01) as HTTP, translates requests into canonical transactions (doc 03), and routes online auth through the active adapter (doc 04). Integrators never see TLV, kernels, or processors — only this.

REST API Surfacethis doc · the only thing integrators touch
Integration / Transaction Enginedoc 01 · 02
Canonical Modeldoc 03
Processor Adapter · Provisioning · Cryptodoc 04 · 05 · 06
ID TECH SDK → readerhardware
Authentication · the front door

Standard OAuth2 client-credentials. An integrator exchanges credentials for a short-lived bearer token, then carries it on every call. Scopes gate which command groups a client may reach, so a status dashboard can't fire a sale.

Auth model OAuth2 · client-credentials
POST /oauth/token
Exchange client_id + client_secret for a bearer token. Returns access_token + expires_in.
Authorization header
Every request carries Authorization: Bearer <token>. No token, no entry — 401.
Scopes
txn:write, txn:read, config:write, device:read — least-privilege per client.
Idempotency-Key
Required on transaction POSTs. A retried request with the same key returns the original result, never a double charge.
why idempotency Networks flake. A client that doesn't get a response and retries must not create a second sale. The Idempotency-Key makes every transaction POST safe to repeat — the server recognizes the key and replays the original outcome. Same discipline as the provisioning reconciler, applied at the API edge.
Endpoints · grouped by what they do

Three groups. Transactions is the core — the v1 feature set. Configuration drives the provisioning feed (doc 05). Device is read-only status. Endpoints marked later are deliberately deferred this iteration.

Transactions /v1/transactions v1 core
POST
/v1/transactions/sale
Auth + capture in one step — the everyday payment. Engages the reader, runs the universal lifecycle, routes online auth through the active adapter, returns the canonical result.
maps to → engage → capture → normalize → adapter.authorize → complete
POST
/v1/transactions/pre-auth
Authorize and hold without capturing — reserves funds. Same lifecycle as sale, but the adapter requests an auth-only message; the kernel cryptogram type reflects hold-not-capture.
maps to → auth-only; awaits a completion
POST
/v1/transactions/{id}/completion
Capture a prior pre-authorization for a final amount (≤ the held amount). References the original by id; the adapter formats the capture/completion message to the processor.
maps to → capture against held pre-auth
GET
/v1/transactions/{id}
Retrieve a transaction's canonical result & state — outcome, response code, masked card, timestamps. Read-only, safe to poll.
POST
/v1/transactions/{id}/void
Reverse a transaction before settlement. References the original by id; the adapter formats the reversal/void message to the processor. Shipped in the C engine as fdy_api_void(), routed through the engine to the active adapter.
maps to → pre-settlement reversal
POST
/v1/transactions/{id}/refund
Return funds against a settled transaction, on the same canonical pattern as sale. Shipped in the C engine as fdy_api_refund(); the adapter formats the refund/credit message to the processor.
maps to → credit against settled txn
POST
/v1/transactions/offline later
Store-and-forward when the host is unreachable. A real subsystem — deferred kernel risk config, queueing, deferred settlement. Named now, built in a later iteration.
Configuration /v1/config provisioning feed
POST
/v1/config/profile
Apply a parameter manifest to the reader — hands off to the provisioning reconciler (doc 05). Idempotent: applies only the delta, verifies by check-value.
maps to → reconcile: diff → set* → verify
GET
/v1/config/profile
Report the currently provisioned manifest version & check-value — what the reader holds right now.
POST
/v1/config/keys/rki
Trigger remote key injection (doc 06, Channel B). Sets the RKI endpoint and starts injection into the secure element — no key material crosses this API.
maps to → device_setSymmetric_RKI_URL → device_startRKI
Device /v1/device read-only status
GET
/v1/device/status
Connection state, firmware version, reader health. The dashboard endpoint — device:read scope only.
GET
/v1/device/ksn
Current Key Serial Number for P2PE reconciliation. A label, not a secret (doc 06).
Pre-auth lifecycle & a sample call

The pre-auth → completion arc as the API sees it, and what a sale request/response looks like on the wire.

POST/pre-auth
funds held, returns {id}
POST/{id}/completion
captured
POST/v1/transactions/sale
// request
{
  "amount": 12500,        // minor units
  "currency": 484,        // MXN
  "reference": "order-8842",
  "language": "es"
}
// header: Idempotency-Key: 9f2a-…
201canonical result
// response
{
  "id": "txn_a1b2c3",
  "state": "completed",
  "outcome": "approved",
  "authCode": "OK1234",
  "responseCode": "00",
  "panMasked": "512345••••0008",
  "entryMode": "contactless"
}
v1 boundary This iteration ships sale, pre-auth, completion, void, and refund, plus config & status. Offline / store-and-forward remains designed-for but deferred — the route is reserved so adding it later is additive, never a breaking change to the surface integrators already built against.
Design rules for the surface

What keeps the API small, safe, and stable as the feature set grows.

Grouped by intent
Transactions, configuration, device. A client reads the surface and knows where everything lives.
Canonical in & out
Requests become canonical transactions; responses are the canonical result. The API is a thin HTTP skin over the mold.
Idempotent writes
Every transaction POST carries an idempotency key. Retries are safe; double charges are impossible.
Scoped tokens
OAuth2 scopes gate each group. Least privilege — a status client can't move money.
Versioned path
/v1 from day one. New capabilities are additive; breaking changes get a new version.
Reserve, don't expose
Refund & offline are designed but deferred. Naming them now keeps the eventual add backward-compatible.