Skip to content
In this section

Fynex Payments API

Accept money and pay it out: hosted checkout, server-to-server card payments, Apple Pay and Google Pay, split payments to marketplace payees, payouts and wallets.

Integration guides and the complete API reference for accepting payments and sending payouts with Fynex. Accept cards, Apple Pay, Google Pay, and bank transfers — and send payouts — with one unified API.

What is Fynex?

Fynex is a unified payments platform that lets you accept money from customers across cards, Apple Pay, Google Pay, and bank transfers, and pay money out to registered counterparties via the banking provider. A single seller-issued bearer token authenticates every call, and the same set of endpoints powers both hosted-checkout and full server-to-server flows.

These docs walk you through the integration end-to-end. Getting started covers your first successful payment. Concepts dives into the data model. Payment flows describes each acceptance method. Payouts covers sending money out. Operations has the operational essentials — idempotency, polling & SSE, errors, reconciliation, and the production checklist. Reference lists every endpoint, parameter, and response — generated from the live OpenAPI spec.

Where to start

  • Quickstart — Take your first test payment in 5 minutes.
  • Hosted checkout — The fastest way to accept a payment with the lowest PCI scope.
  • Server-to-server — Full control of the flow when you collect card data on your own server.
  • Payouts — Move money out from a wallet to a registered payee.
  • Going live — Production checklist: tokens, monitoring, and the launch playbook.

Invoices, subscriptions, contracts, metered usage and credit balances live on their own surface, /billing-api/v1, documented at /billing-api/v1/docs with the machine contract at /billing-api/v1/openapi.json. It authenticates with the same seller secret key. One convention difference to know before writing code: Billing carries money exclusively as integer minor units in fields ending Minor, while this API's checkout takes major units — see Amounts and currency.

Welcome to the Fynex Payments API

Fynex is a unified payments platform for accepting cards, Apple Pay, Google Pay, and bank transfers, plus moving money out via payouts. This reference describes every endpoint a seller integration needs.

All routes live under /payments-api/v1 and authenticate with a seller bearer token. You can mint a token from the Fynex Dashboard.

Base URLs

  • Production: https://api.fynex.ai/payments-api/v1

The OpenAPI document's servers block declares the origin of the deployment serving it. Each entry is the bare origin; the /payments-api/v1 prefix is already part of every path in the document.

Which host you call does not decide whether money is real: that follows your account's operational mode. A Demo account is a sandbox account on any host.

Versioning

Every operation is served under /payments-api/v1 — there is no /v2 operation surface. /payments-api/v2 carries only the documentation for that same contract (/payments-api/v2/docs, /openapi.json, /llms.txt), because it was the path the current spec was first published under during the docs migration. A request to /payments-api/v2/initialize-payment answers 404.

Call /payments-api/v1. Reading the reference at /v2/docs does not put you on a newer contract; there is only one.

When a genuinely incompatible version ships it will be a new prefix, announced before it lands, and this section will say what changed and by when the old one stops. Until then there is one contract.

How a change is signalled

Additive changes — a new endpoint, a new optional field, a new enum value — ship without notice, so write clients that ignore fields they do not recognise and do not fail on an unknown enum value.

Anything being withdrawn is marked deprecated: true in openapi.json before it goes, on the field, schema or operation itself. A renamed schema keeps its former name published as a deprecated alias pointing at the replacement, so a client generated against the older document still resolves. Read the spec, not just the guides: the deprecation markers are in the schema, which is where a generated client and an agent will see them.

Support and deprecation policy

Payments and Billing use the same shared public API lifecycle and deprecation policy. The terms below apply consistently to both public API references.

A public major version remains supported for at least 12 months after its successor becomes generally available. We give integrators at least 90 calendar days of notice before removing a public operation, field or enum value from a supported major version. Each notice names the replacement (when there is one), the migration action and the planned removal date in the public Changelog.

The OpenAPI deprecated: true marker is the machine-readable signal. For an HTTP operation with a scheduled retirement, the changelog entry records the planned Deprecation and Sunset response headers: Deprecation will say the operation is no longer the preferred integration path, and Sunset will give its planned last-availability date. No HTTP operation has a scheduled retirement today, so neither header is currently emitted. A critical security, legal or abuse response may need an earlier withdrawal; if that happens, we publish the reason and the affected contract in the Changelog as soon as it is safe to do so.

Integration paths

Pick the flow that fits your product:

  • Hosted checkout — call POST /checkout, redirect the buyer to the returned URL, receive the result via webhook. Lowest PCI scope.
  • Server-to-server — call POST /initialize-payment, complete any 3DS challenge client-side, then call POST /finalize-payment. You handle card data.
  • Capture / refund — once a payment is authorized or captured, use POST /payments/{payment_id}/capture and /refund for the full amount or partials.
  • Payouts — POST /payouts to send money from a wallet to a registered payee's payout method.
  • Top-up invoices — POST /payments-api/v1/topup-invoices issues an invoice a buyer settles by bank transfer, funding the seller's wallet once the deposit is matched. Enabled per deployment (404 where it is off); ask Fynex before building on it.

The open top-up invoice cap

A seller may hold at most 20 open top-up invoices at a time — open being pending, outdated or marked_paid. Issuing the twenty-first answers 422 with too many open top-up invoices; settle or cancel one and the same request succeeds.

The bound exists because every issued invoice burns one number from the shared (agreement number, YYMM) invoice-number series, which is also drawn on by billing and settlement invoices. It is a supply bound, not a rate limit: retrying the same request without clearing an open invoice will keep answering 422, and there is nothing to back off for.

Errors

Errors return JSON in the form { "error": "<message>", "code": "<code>" }: code is specific where the API can say more than the status, and otherwise derived from it (bad_request, not_found, conflict, …). Status codes follow the usual conventions:

Code Meaning
400 Validation error
401 Missing or invalid bearer token
404 Resource not found for this seller
409 Conflict (e.g., invalid status transition, duplicate refund)
422 The request is well formed but not applicable in the seller's current state (e.g., the open top-up invoice cap above)
500 Internal error
502 Upstream provider failure

Amounts and currency

Request amounts are major units everywhere on this API (e.g. 19.99), with one exception: a split share in orderData.payeeDistribution takes amountMinor, integer minor units (its major-units amount is deprecated). Payouts take them as a decimal string ("amount": "19.99"); the integer amountMinor on payouts is a deprecated fallback that amount overrides when both are sent. Currencies are ISO 4217 codes (GBP, EUR, USD).

Error format

Every error returns JSON with an error and a machine-readable code. Branch on code, never on the error text, which may be reworded:

{ "error": "This card has expired. Please use a different card.", "code": "card_expired" }

code is specific where the API can say more than the status (card_expired above); otherwise it is derived from the status — bad_request, unauthorized, forbidden, not_found, conflict, unprocessable_entity, rate_limited, internal_error, bad_gateway and so on.

Status codes:

Code Meaning
400 Validation error
401 Missing or invalid bearer token
404 Resource not found for this seller
409 Conflict (e.g., invalid status transition, duplicate refund). A refund refused by the seller balance check carries code insufficient_balance (the main wallet cannot cover the refund plus its fee), balance_settling (retry later: the payment's balance is still settling) or refund_requires_review (Fynex must review the payment first); no refund was created
422 Card refused with no funds moved (code: card_expired, card_brand_not_supported) — ask for a different card. On POST /checkout and payment-link creation, code currency_not_supported: no terminal of the account can take the currency (or declared country), and nothing was created
500 Internal error
502 Upstream provider failure

Quoting a failure to support

Every response carries X-Request-Id — a req_-prefixed identifier generated at the boundary, on failures as well as successes, and on a 404 for a URL that does not exist. Log it alongside your own request and quote it when reporting a problem: it is what turns "a call failed this morning" into one line in ours.

It is generated here and never taken from your request, so it is a correlation id and not a field you can set. If you need to carry your own, send it in a header of your own choosing — and note that on writes, Idempotency-Key is the one caller-supplied value this API does act on.

Amounts and currency

Request amounts are major units everywhere on this API (e.g. 19.99). Payouts take them as a decimal string ("amount": "19.99"); the integer amountMinor on payouts is a deprecated fallback that amount overrides when both are sent. Responses add …Minor integer twins where the wire needs them. Currencies are ISO 4217 codes (GBP, EUR, USD).

Read the field name before the value — this is where the 100× mistake lives. The platform's house convention (the Billing API follows it throughout, and new Payments fields adopt it) is:

Value Type Field name Example
Money amount Integer, minor units ends Minor 4999 is £49.99
Rate / percentage Integer, basis points ends Bps 275 is 2.75%
Quantity Decimal string — "1250.5"
Tax rate Decimal string, percent — "20.0"

Checkout's major-unit fields predate that convention and remain accepted. The trap is real in both directions: 49.99 sent into a …Minor field underpays a hundredfold, and 4999 sent into checkout's totalAmount overcharges by the same factor — neither errors. When a field name ends Minor, it is an integer count of the currency's smallest unit, everywhere, on both APIs.