Tapaya
OverviewPlatform APIMerchant Onboarding API

Merchant Onboarding API

Create merchants and submit or invite them to onboarding through the Tapaya Platform API.

All requests on this page use your Server Secret Token. See Authentication.

One onboarding for In-Store and Online

A merchant onboards once and the same onboarding covers both In-Store Acceptance and Online Payments. This page applies to every integration: the Accept SDK, the Tapaya Terminal app, and Checkout. Use it to create and manage merchants through the API instead of the Tapaya Platform UI. If your merchants already complete onboarding inside the Tapaya Terminal app, you can skip this page.

Creating a merchant with POST /integrator/merchant, or with POST /merchant/auth/register in an Accept SDK integration, creates its account, but the merchant cannot process live payments in store or online until onboarding is complete. To take online payments after onboarding, also enable Checkout in Checkout settings. Tapaya supports several onboarding experiences; all can be managed from the Tapaya Platform UI and automated where appropriate.

FlowWhen to use itAPI entry point
Tapaya Platform UIYour operations team completes onboarding on the merchant's behalf.Create or select the merchant in the Tapaya Platform UI and open the hosted onboarding there.
Your own UIYou collect and validate onboarding information in your product.Validate sections with POST /integrator/merchant/onboarding/validate/*, then submit with POST /integrator/merchant/onboarding. Detailed below.
Email inviteA known merchant receives a single-use invitation to self-onboard.Send an invite with POST /integrator/merchant/send-registration-invite; include merchantToken to bind the invite to an existing merchant shell, then list or revoke it through /integrator/merchant/invites.
Campaign linkMultiple or not-yet-known merchants use a reusable self-registration link.Create a link with POST /integrator/merchant/reusable-registration-invites; list or revoke links through the same resource.

For a detailed comparison of these flows, see the Merchant Onboarding guide.

Invite a Merchant to Complete Hosted Onboarding

Use this flow when Tapaya should host the KYB form, but you still want to control merchant creation from your backend.

Recommended when you own merchantToken

If your system owns the merchant identifier used later by the SDK or your back office, first create the merchant shell with POST /merchant/auth/register or POST /integrator/merchant, then call POST /integrator/merchant/send-registration-invite with the same merchantToken. This keeps the hosted onboarding attached to that merchant instead of creating a second one.

The recommended sequence is:

  1. Create the merchant shell:
    • POST /merchant/auth/register, or
    • POST /integrator/merchant
  2. Send the hosted onboarding invite with POST /integrator/merchant/send-registration-invite
  3. Share the returned registrationUrl with the merchant if needed, and let them complete the Tapaya-hosted form
  4. Poll merchant readiness through GET /integrator/merchant/{merchantId}/status

Endpoint: POST /integrator/merchant/send-registration-invite

curl -X 'POST' 'https://api.tapaya.com/integrator/merchant/send-registration-invite' \
-H 'Content-Type: application/json' \
-H 'Authorization: REPLACE_ME' \
-d '{
        "email": "admin@acme.com",
        "merchantToken": "unique_merchant_id_from_your_db"
    }'

Parameters:

FieldTypeRequiredDescription
emailstring✓Email address that should receive the hosted onboarding link.
merchantTokenstringExisting merchant token to bind the invite to. Use this when you already created the merchant shell and want the hosted onboarding to fill that same merchant. If omitted, completing the invite creates a new merchant.

Responses:

CodeDescription
200Invite created. Response includes registrationUrl
400Request validation error
401Unauthorized
404Organization or merchant not found
409Conflict

Response body:

{
    "registrationUrl": "https://platform.tapaya.com/invite-merchant?token=...&merchantToken=unique_merchant_id_from_your_db"
}

Tapaya also attempts to email this link. Email delivery is best-effort, so always treat the returned registrationUrl as the source of truth for your UI and support tooling.

Do not confuse this with merchant-user invite

POST /integrator/merchant/{merchantId}/invite is a different flow. It invites a platform user to access an already-existing merchant account. It does not start KYB onboarding and does not create or update a merchant profile.

Submit Onboarding through the API

If you want to collect onboarding information in your own product instead of sending merchants to the Tapaya Platform, submit it directly. Validate each section as the merchant fills it in with the validate/* endpoints below, then submit everything in one call, which creates the merchant and its onboarding profile together, and registers it with your organization's preferred payment processor.

Merchant not created on failure

POST /integrator/merchant/onboarding creates the merchant and submits onboarding in a single call. If the onboarding data is invalid, it returns 422 with field-level errors and no merchant is created; there is no partially-onboarded merchant to clean up or resume.

Validate Identity

Endpoint: POST /integrator/merchant/onboarding/validate/identity

curl -X 'POST' 'https://api.tapaya.com/integrator/merchant/onboarding/validate/identity' \
-H 'Content-Type: application/json' \
-H 'Authorization: REPLACE_ME' \
-d '{
        "legalName": "Acme Corp s.r.o.",
        "businessTypeId": 2,
        "email": "admin@acme.com",
        "registrationNumber": "12345678",
        "vatNumber": "CZ12345678",
        "incorporationDate": "2018-04-01"
    }'

Parameters:

FieldTypeRequiredDescription
legalNamestring✓Legal name of the business or individual account holder.
businessTypeIdint✓Type of business entity (BusinessTypeEnum).
emailstring✓Contact email address.
registrationNumberstring✓Official business registration number. Checked for duplicates within your
organization.
vatNumberstringVAT registration number, if applicable.
incorporationDatedateDate the business was legally incorporated (YYYY-MM-DD).

Response body:

{
    "valid": true,
    "errors": []
}

A registrationNumber already used by another merchant in your organization comes back as a valid: false error with code: "DUPLICATE_REGISTRATION_NUMBER" rather than a 409; this endpoint always returns 200.

Validate Address

Endpoint: POST /integrator/merchant/onboarding/validate/address

curl -X 'POST' 'https://api.tapaya.com/integrator/merchant/onboarding/validate/address' \
-H 'Content-Type: application/json' \
-H 'Authorization: REPLACE_ME' \
-d '{
        "line1": "Wenceslas Square 1",
        "city": "Prague",
        "postalCode": "11000",
        "countryId": 1
    }'

Parameters:

FieldTypeRequiredDescription
line1string✓First line of the street address.
line2stringSecond line of the street address, if applicable.
citystring✓City name.
postalCodestring✓Postal or ZIP code.
statestringState or region, if applicable.
countryIdint✓Country (CountryEnum).

Response body: same {valid, errors} shape as Validate Identity.

Validate Business Profile

Endpoint: POST /integrator/merchant/onboarding/validate/business

curl -X 'POST' 'https://api.tapaya.com/integrator/merchant/onboarding/validate/business' \
-H 'Content-Type: application/json' \
-H 'Authorization: REPLACE_ME' \
-d '{
        "mcc": "5411",
        "url": "https://acme.example.com",
        "supportPhone": "+420123456789",
        "statementDescriptor": "ACME CORP"
    }'

Parameters:

FieldTypeRequiredDescription
mccstring✓Four-digit Merchant Category Code.
urlstringBusiness website URL. Either url or productDescription is required.
productDescriptionstringDescription of products or services. Either url or productDescription is
required.
supportPhonestring✓Customer support phone number, in E.164 format.
statementDescriptorstring✓Text shown on customer bank statements (1–22 characters).
averageItemValuelongAverage transaction value, in minor currency units.
expectedMonthlyTurnoverlongExpected monthly revenue, in minor currency units.
numberOfEmployeesintNumber of employees at the business.
annualTurnoverlongAnnual revenue, in minor currency units.
balanceSheetTotallongTotal balance sheet value, in minor currency units.

Response body: same {valid, errors} shape as Validate Identity.

Validate KYB

Endpoint: POST /integrator/merchant/onboarding/validate/kyb

Provide exactly one of individual (sole trader / self-employed) or company. For a company, list every owner, director, and authorized signatory in people.

curl -X 'POST' 'https://api.tapaya.com/integrator/merchant/onboarding/validate/kyb' \
-H 'Content-Type: application/json' \
-H 'Authorization: REPLACE_ME' \
-d '{
        "businessTypeId": 2,
        "bankAccount": {
            "iban": "CZ6508000000192000145399",
            "bic": "GIBACZPX",
            "currencyId": 1,
            "beneficiaryName": "Acme Corp s.r.o."
        },
        "company": {
            "name": "Acme Corp s.r.o.",
            "registrationNumber": "12345678",
            "people": [
                {
                    "email": "jane@acme.com",
                    "firstName": "Jane",
                    "lastName": "Doe",
                    "role": {
                        "isOwner": true,
                        "isAuthorizedSignatory": true
                    }
                }
            ]
        }
    }'

Parameters:

FieldTypeRequiredDescription
businessTypeIdintType of business entity (BusinessTypeEnum); determines whether individual or
company fields are required.
bankAccountobjectPayout bank account (account number/IBAN + BIC, currency, beneficiary and bank
address).
individualobjectIndividual owner details, for sole traders. Mutually exclusive with company.
companyobjectCompany details, including a people array of owners, directors, and authorized
signatories, plus an optional verificationDocument. Mutually exclusive with individual.

Each person in people (and individual) carries role.isOwner / isDirector / isRepresentative / isAuthorizedSignatory flags, plus optional identity fields (dateOfBirth, nationalityCountryId, officialIdType/officialIdNumber, address, ownershipPercentage, verificationDocuments). A person entry must be either invite-only or fully detailed; partially filled people are rejected. There are two ways to submit a person:

  • Invite-only: submit just email and a role. The person receives an email with instructions to complete their own personal details and identity verification directly, including uploading their own ID document; you don't need to collect anything else for them, and no document upload is required on your side.
  • Fully detailed: submit all of the person's personal details (name, date of birth, official ID, address, etc.) yourself. In this case you must also upload an ID document for that person; this is required, not optional, for every fully-detailed person.

Documents are uploaded after the merchant exists, because the document upload endpoint needs the merchantId returned by Create Merchant with Onboarding. Each person's upload is matched to them by relatedOfficialIdNumber. The optional verificationDocuments.identityDocument, verificationDocuments.additionalDocument, and company.verificationDocument fields each take a {frontFileId, backFileId} object and can only reference files that were already uploaded, so omit them when creating a new merchant.

Regardless of how many people are invite-only vs. fully detailed, you must always upload the company's registration/incorporation document before the merchant can be submitted for KYC review.

Response body: same {valid, errors} shape as Validate Identity.

Create Merchant with Onboarding

Submits everything from the previous four steps in one call, creates the merchant, and registers it with your organization's preferred payment processor.

Endpoint: POST /integrator/merchant/onboarding

curl -X 'POST' 'https://api.tapaya.com/integrator/merchant/onboarding' \
-H 'Content-Type: application/json' \
-H 'Authorization: REPLACE_ME' \
-d '{
        "name": "Acme Corp",
        "merchantToken": "unique_merchant_id_from_your_db",
        "identity": {
            "legalName": "Acme Corp s.r.o.",
            "businessTypeId": 2,
            "email": "admin@acme.com",
            "registrationNumber": "12345678",
            "vatNumber": "CZ12345678"
        },
        "address": {
            "line1": "Wenceslas Square 1",
            "city": "Prague",
            "postalCode": "11000",
            "countryId": 1
        },
        "business": {
            "mcc": "5411",
            "url": "https://acme.example.com",
            "supportPhone": "+420123456789",
            "statementDescriptor": "ACME CORP"
        },
        "kyb": {
            "bankAccount": {
                "iban": "CZ6508000000192000145399",
                "bic": "GIBACZPX",
                "currencyId": 1,
                "beneficiaryName": "Acme Corp s.r.o."
            },
            "company": {
                "people": [
                    {
                        "email": "jane@acme.com",
                        "firstName": "Jane",
                        "lastName": "Doe",
                        "role": {
                            "isOwner": true,
                            "isAuthorizedSignatory": true
                        }
                    }
                ]
            }
        }
    }'

Parameters:

FieldTypeRequiredDescription
namestring✓The name of the merchant.
merchantTokenstringA unique, stable identifier from your system. If not provided, a random token is
generated.
identityobject✓Same shape as Validate Identity.
addressobject✓Same shape as Validate Address.
businessobject✓Same shape as Validate Business Profile.
kybobject✓Same shape as Validate KYB.

Responses:

CodeDescription
201Merchant created and onboarding submitted
422Onboarding data invalid, see errors; merchant is not created

Response body (201):

{
    "merchantId": "018f8f2a-3b1e-7c2a-9f1a-2e6a1b7c4d3e",
    "merchantToken": "unique_merchant_id_from_your_db",
    "name": "Acme Corp",
    "email": "admin@acme.com",
    "processors": [
        {
            "processorId": 5,
            "registered": true,
            "onboardingUrl": null
        }
    ]
}

onboardingUrl is populated when the processor requires the merchant to complete an additional hosted onboarding flow (e.g. identity verification) before it can process live payments.

Response body (422):

{
    "errors": [
        {
            "step": "identity",
            "field": "registrationNumber",
            "message": "A merchant with this registration number is already onboarded under this integrator (merchantId: 018f8f2a-3b1e-7c2a-9f1a-2e6a1b7c4d3e).",
            "code": "DUPLICATE_REGISTRATION_NUMBER"
        }
    ]
}

Upload a Person's ID Document

Required for every fully-detailed person in kyb.company.people / kyb.individual (see Validate KYB); invite-only people upload their own instead, via the emailed link.

Endpoint: POST /integrator/merchant/{merchantId}/document

Request body is multipart/form-data, not JSON.

curl -X 'POST' 'https://api.tapaya.com/integrator/merchant/018f8f2a-3b1e-7c2a-9f1a-2e6a1b7c4d3e/document' \
-H 'Authorization: REPLACE_ME' \
-F 'paymentProcessorId=5' \
-F 'documentType=2' \
-F 'relatedOfficialIdNumber=123456789' \
-F 'frontFile=@./jane-doe-id-front.jpg' \
-F 'backFile=@./jane-doe-id-back.jpg'

Parameters:

FieldTypeRequiredDescription
paymentProcessorIdint✓Always 5.
documentTypeint✓Type of document (DocumentTypeEnum: 1 Other, 2 Id, 3 Address, 4 Company,
5 BankStatement, 6 Passport, 7 RecentFinancials).
frontFilefile✓Front side of the document image.
backFilefileBack side of the document image, if applicable.
relatedOfficialIdNumberstringThe person's officialIdNumber from Validate KYB.
Required only when documentType is individual-bound (e.g. Id, Passport, Address); ignored otherwise.
submitMerchantbooleanLeave unset/false here: a person's ID is not the final upload of the batch.
Only set true on the company document upload once every person's document has been
uploaded.

Response body (200):

{
    "frontFileId": "file_1NqtHo2eZvKYlo2CZPg8Xt5h",
    "backFileId": "file_1NqtHp2eZvKYlo2CRTg9Xm3k",
    "uploadedAt": "2026-07-17T12:00:00Z"
}

Upload the Company Document

Required exactly once per merchant. If person details were not filled in, the authorized signatory will be able to upload this using the link from the onboarding email and this endpoint does not need to be called.

Endpoint: POST /integrator/merchant/{merchantId}/document

Request body is multipart/form-data, not JSON.

curl -X 'POST' 'https://api.tapaya.com/integrator/merchant/018f8f2a-3b1e-7c2a-9f1a-2e6a1b7c4d3e/document' \
-H 'Authorization: REPLACE_ME' \
-F 'paymentProcessorId=5' \
-F 'documentType=4' \
-F 'frontFile=@./acme-corp-register-extract.pdf' \
-F 'submitMerchant=true'

Parameters:

FieldTypeRequiredDescription
paymentProcessorIdint✓Always 5.
documentTypeint✓Always 4 (Company) for this step.
frontFilefile✓The company's registration/incorporation document.
submitMerchantbooleanSet to true to trigger the processor's KYC review now that every required
document has been uploaded. Defaults to false.

Response body (200):

{
    "frontFileId": "file_1NqtHo2eZvKYlo2CZPg8Xt5h",
    "backFileId": null,
    "uploadedAt": "2026-07-17T12:00:00Z"
}