Vendors
Onboard sub-merchants (vendors) under a platform account — create, screen, and pay marketplace vendors through the REST API.
A vendor is a sub-merchant you onboard under your platform account in the merchant-of-record model: your buyers pay you, and you pass each vendor its share. Fynex screens every vendor from the details you supply, holds it to a cumulative payout limit until it completes verification, and gives you one payee per vendor to pay it through.
The vendor surface is available to Platform accounts only, using the platform's own API key. A merchant account, or a delegated dashboard session, receives 403 platformRequired.
Note
These endpoints are enabled per environment. If
POST /payments-api/v1/vendorsanswers404on your account, ask support to enable vendor onboarding for you.
Lifecycle
Every vendor response carries a verification block. verification.status is the one field to branch on:
verification.status |
Meaning | payoutsEnabled |
|---|---|---|
pending_fynex |
Fynex is screening (reason: screening) or reviewing. Nothing for you or the vendor to do. |
false |
not_required |
Screening passed; no verification step is due. | true, under the cumulative limit |
required |
The vendor must complete a step. Fetch the link with POST /vendors/{vendor_id}/verification-link and hand it to the vendor. |
true until the limit is reached |
in_progress |
The vendor has started the step. | unchanged |
complete |
Fully verified; the cumulative limit no longer applies. | true |
blocked |
Refused at screening (reason: screening_refused), declined at verification (reason: declined) or manually blocked (reason: blocked). |
false, permanently |
Screening is non-interactive: the vendor is not contacted and uploads nothing. You supply the identity (company number + country, or name + date of birth + country) and Fynex screens it against sanctions, politically-exposed-person and adverse-media lists. It usually completes within the request; otherwise poll GET /vendors/{vendor_id} until verification.status leaves pending_fynex.
paymentsEnabled is always false: in the merchant-of-record model the vendor never takes a payment itself.
Create a vendor
POST /payments-api/v1/vendors
Authorization: Bearer <platform_sk_key>
Content-Type: application/json
{
"externalRef": "vendor_8817",
"entityType": "company",
"displayName": "Blue Door Ceramics Ltd",
"contactEmail": "owner@bluedoor.example",
"country": "GB",
"companyNumber": "09876543",
"merchantCategoryCode": "5999",
"storefrontUrl": "https://market.example/shops/blue-door",
"address": { "street": "1 High Street", "city": "Edinburgh", "postalCode": "EH1 1AA" },
"consent": { "sumsubPrivacyNoticeAccepted": true, "acceptedAt": "2026-09-03T12:00:00Z", "ip": "203.0.113.7", "noticeVersion": "2026-07" }
}
For an individual (sole trader), send "entityType": "individual" with a person object instead of companyNumber:
"person": { "firstName": "Jane", "lastName": "Maker", "dob": "1990-04-12" }
dob is required (YYYY-MM-DD; the vendor must be at least 18). displayName is the registered name for a company and the trading name for an individual. merchantCategoryCode is the four-digit MCC describing what the vendor sells; it is required and screened. storefrontUrl is the vendor's page on your marketplace (https). consent is your attestation that the vendor accepted the verification provider's privacy notice on your side; it is required (422 consentRequired) once consent enforcement is on for your environment, and recorded whenever you send it.
{
"vendorId": "7c1f8a2e-6b3d-4e5f-9a0b-1c2d3e4f5a6b",
"externalRef": "vendor_8817",
"entityType": "company",
"displayName": "Blue Door Ceramics Ltd",
"paymentsEnabled": false,
"payoutsEnabled": false,
"payeeId": 101,
"verification": { "status": "pending_fynex", "reason": "screening", "actionUrl": null, "actionExpiresAt": null },
"payoutAllowance": { "currency": "GBP", "limitMinor": 10000, "usedMinor": 0, "remainingMinor": 10000,
"basis": "cumulative_lifetime_all_currencies", "enforcement": "monitored", "unlimited": false, "deferred": false },
"nextTier": { "limitMinor": null, "unlimited": true,
"requirements": [ { "code": "screening_passed", "status": "in_progress" },
{ "code": "identity_verification", "status": "not_started" },
{ "code": "agreement_signed", "status": "not_started" } ] },
"createdAt": "2026-09-05T12:00:00Z",
"updatedAt": "2026-09-05T12:00:00Z"
}
201 Created on creation. When the screening completes synchronously the verdict is applied before the response is written, so the first response is often already not_required with payoutsEnabled: true.
Idempotency
externalRef is your identifier for the vendor and is unique within your platform. Re-sending an equivalent request (whitespace and letter case do not count) for the same reference returns the existing vendor with 200 OK — safe to retry after a timeout. The same reference with a different body is 409 externalRefConflict: you are reusing a reference for a different vendor.
Responses
All errors use the standard envelope {"error": "<code>"}. Field-level validation failures name the field: {"error": "person.dob: required; YYYY-MM-DD"}.
| Status | error |
When |
|---|---|---|
201 |
— | Vendor created |
200 |
— | Idempotent replay of an equivalent request |
400 |
<field>: <reason> |
A field is missing or malformed |
401 |
Missing or invalid Bearer token | |
403 |
platformRequired |
Your account is not an active platform, or the credential is a delegated dashboard session rather than the platform's own key |
409 |
externalRefConflict |
externalRef already refers to a vendor created with a different request |
422 |
invalidCountry |
country is not an ISO 3166-1 alpha-2 code |
422 |
countryNotSupported |
A real country Fynex does not onboard vendors from |
422 |
mccProhibited |
The merchant category is prohibited |
422 |
vendorScreeningRefused |
This vendor cannot be onboarded through the API. Contact support if you believe this is wrong |
422 |
consentRequired |
Consent enforcement is on and consent.sumsubPrivacyNoticeAccepted was not true |
429 |
dailyVendorLimitReached |
Daily vendor creation limit for your platform; retry after 24 hours |
503 |
screeningUnavailable |
Screening is temporarily unavailable. Nothing was created; retry with the same externalRef |
The vendor mutation routes also have their own per-platform rate-limit bucket, separate from the general API limit; a 429 carrying Retry-After and the JSON body {"error":"rate limit exceeded; retry after the Retry-After header value","code":"rate_limited"} is that bucket.
Read vendors
GET /payments-api/v1/vendors/{vendor_id}
GET /payments-api/v1/vendors?limit=20&offset=0
The list is newest first and paginated like /payees (limit 1–100, default 20). A vendor that belongs to another platform, or does not exist, is 404 vendorNotFound.
Verification link
When a vendor's verification.status becomes required — you receive MarketplaceVendorVerificationRequired if you subscribed to the vendor events, and GET /vendors/{vendor_id} shows it — request a link and hand it to the vendor:
POST /payments-api/v1/vendors/{vendor_id}/verification-link
Authorization: Bearer <platform_sk_key>
{ "actionUrl": "https://…", "actionExpiresAt": "2026-09-06T12:00:00Z" }
The vendor opens the link and completes verification with the provider; you are not involved in the flow itself. Every call mints a fresh link (the previous one stays valid until its own expiry), so call it again if the vendor lost theirs. The link is bearer-like: send it over a channel you trust and do not log it.
| Status | error |
When |
|---|---|---|
200 |
— | Link minted |
403 |
platformRequired |
Not the platform's own key |
404 |
vendorNotFound |
Not your vendor |
409 |
verificationNotRequired |
No step is due for this vendor |
503 |
screeningUnavailable |
The provider could not mint a link; retry |
As the vendor progresses, verification.status moves through in_progress and pending_fynex to complete (or blocked), and the matching MarketplaceVendorVerification* events fire.
Paying a vendor
Each vendor has exactly one payee (payeeId), owned by your platform account. Use it exactly like any other payee:
- Attach bank details:
POST /payees/{payee_id}/payout-methods— see Payout methods. - Route the vendor's share: name the payee in a split rule — see Splits.
- Pay out:
POST /payoutsfrom the payee's wallet — see Payouts.
The payee is disabled while verification.status is pending_fynex and stays disabled if the vendor is blocked: a split naming it is refused at payment time, so no funds can accrue to an unscreened vendor. It is enabled the moment the screening passes.
The cumulative payout limit
A screened vendor may receive up to £100 (or equivalent) in cumulative payouts before it must complete full verification. payoutAllowance shows where the vendor stands: limitMinor and usedMinor in GBP minor units (payouts in other currencies count at the current reference rate), remainingMinor what is left, and enforcement what happens at the boundary — monitored means a crossing is detected after the fact and verification is requested; held_for_review means a payout that would cross the limit waits for Fynex compliance. deferred: true means the total could not be computed right now (a payout currency has no current rate); nothing is enabled or disabled by it.
When a vendor crosses the limit Fynex asks it to verify and notifies you (verification.status: required). Vendors that complete verification show unlimited: true and no longer have a cumulative limit.
nextTier says exactly what lifts the limit: three requirements — screening_passed (Gate 1, automatic), identity_verification (the vendor completes verification via the link above) and agreement_signed (the vendor signs the seller agreement Fynex sends at the crossing) — each complete, in_progress or not_started. Once all three are complete the vendor is unlimited and nextTier.requirements is empty.
What vendors are not
- A vendor is not a seller account you can authenticate as. It has no API key and no dashboard login; you operate it through your platform key.
- A vendor is not a payee you create yourself. Creating a payee directly (
POST /payees) gives you a payout counterparty without screening; creating a vendor gives you a screened sub-merchant with a payee. Use vendors for sub-merchants whose goods or services your buyers pay you for.