Skip to main content

Apply for TagadaPay Processing

Who this is for: a direct merchant who wants TagadaPay to process their cards — the same flow as Dashboard → New Request at dashboard.tagadapay.io.Not a partner? You’re in the right place. Authenticate with a CRM key (sk_crm_…) and call processing.applications.create().Building a platform for many sub-merchants? Use the Partners guide and partners.processing.tpas.create() instead — partners never use this endpoint.
A processing application is how you ask TagadaPay to onboard you as a processor customer. Submit it with a CRM key, it lands in our review queue, our team runs KYB, and provisions your TPA. The payload mirrors the dashboard “New Request” form 1:1 — the exact data our acquiring network runs KYB/KYC on. The more complete and accurate it is, the faster you are approved.

What you’re applying for: a TPA

Approval gives you a TagadaPay Account — a TPA (id prefix tpa_xxx). The TPA, not your login and not your store, is the object that actually holds one KYB-approved legal entity, its assigned acquirer, its settlement bank account, and its own charging scope. It sits under your merchant account — the thing you log into and hold a single CRM key for:
The important part: one application provisions one TPA, and a single merchant can own many of them (acc_xxx → 0..N tpa_xxx). See One merchant, many TPAs for why you’d want that and how to do it.

The three field tiers

Every field is one of three tiers — the SDK types tag each one, and your editor autocompletes the full set:

Required

The API rejects the application without it (400 missing_required_fields). Non-optional in the types.

Recommended

Not enforced at intake, but acquirers will ask for it before activation. Omitting one only delays approval — create() echoes the gaps in recommendations, and the review queue flags every one.

Optional

Situational / nice-to-have. Improves risk underwriting but is never blocking.
Only 5 fields are strictly required: businessInfo.businessName, businessInfo.country, and the representative’s firstName, lastName, email. Everything else is recommended or optional — but a 5-field application will bounce back from KYB. Send a complete one.

Minimal vs complete

A complete application — the shape you actually want to send. The payload is the same everywhere; only the country-specific identifiers and settlement rail change. Pick your jurisdiction:
Either way, create() returns the same shape:

Field reference

businessInfo

US merchants — registrationNumber and taxId are the same EIN. The US has no separate company registration number, so the federal EIN (e.g. 98-1923816) is both your tax ID and your registration number. Send the same 9-digit value in both fields. The acquirer requires both to be present.

representative

The legal representative — the UBO / authorised signer who is the KYC subject.

bankAccount

Settlement (payout) account. The account holder must match the legal entity — acquirers reject payouts to a mismatched name. Provide one rail.

documents

Optional at submit, but they satisfy KYB requirements early. Each entry is metadata referencing a file you’ve already uploaded to storage:
Accepted type values: passport, drivers_license, national_id, proof_of_national_id, proof_of_address, business_registration, bank_statement, processing_history, id_scan, other.

How recommendations works

create() never fails on a missing recommended field. Instead it returns them so you can surface them in your own UI or fill them later:
The same gaps appear as “Missing” pills in the TagadaPay dashboard once your application is in review.

Pre-submission document audit

The #1 reason an application is not accepted by the acquirer on the first try is a mismatch between an uploaded document and the declared data — a passport whose name differs from representative, an ID issued by a different country than nationality, a registration document for another company name, or a file uploaded under the wrong type. The SDK can catch these before you submit.

Audit each document right after upload

auditDocument reads the file (SumSub’s validated read for identity documents when available, otherwise an AI document analysis), extracts the key fields, and compares them to what you declared. It returns:
Everything is advisory and non-blockingissues: [] means the document looks consistent. It is best-effort: an unreadable file returns { issues: [], source: 'none' }.

documentWarnings on submit

create() runs the same audit across all uploaded documents and echoes any findings in documentWarnings (present only when something was found):
Common code values: doc_type_mismatch, name_mismatch, issuer_country_mismatch, company_name_mismatch, registration_number_mismatch, cross_border_residency, missing_for_declared.

Why the SDK asks for less than the dashboard “requires”

The dashboard form visually marks ~15 fields as required (red pills). Only 5 are hard gates; the rest are the Recommended tier above. A complete SDK application and a complete dashboard application carry identical data.

Track the application

Once approved and your TPA is provisioned, tpaId is populated. Then enroll to mint a processing key and start charging.

One merchant, many TPAs

A TPA is scoped to one legal entity with one settlement setup. That is deliberate: KYB is run per entity, and an acquirer is assigned per entity. So whenever your reality has more than one of those, you want more than one TPA — all owned by your single merchant account. Common reasons to run several:
One application = one TPA. You don’t get multiple TPAs from a single submission — you get them by submitting one application per entity (or region). Every application you send with the same CRM key attaches to the same merchant (acc_xxx), so they all collect under one account you manage with one key.

Example: three LLCs, one merchant

Say you operate three US LLCs. Each is a separate legal entity, so each needs its own application — but you submit them all from the same CRM key:
Same entity, several regions? Use the exact same loop, but vary businessInfo.country and the settlement rail per region — e.g. one application with country: 'FR' + an EUR iban/bic, and another with country: 'US' + a USD routingNumber/accountNumber. You’ll end up with an EU TPA and a US TPA under the same merchant.

After approval: one key for all your TPAs

Once your applications are approved and their TPAs are provisioned, call enroll() once. It mints a merchant-scoped processing key (tp_sk_…) that can see and manage every TPA under your account — you do not enroll per TPA.
enroll() is activation without leaving your code. It does the same thing as going to the TagadaPay dashboard, activating processing, and copying your key — the SDK just lets you do it (and the whole apply → KYB → charge flow) end to end, without ever opening the CRM or the dashboard.Because of that, treat key minting as a one-time setup step, not application code: run enroll() once in a bootstrap script (or grab the key from the dashboard), store key.secret in your secrets manager, and have your app read it from the environment. Minting a key inside your request path is the equivalent of re-running a seeding script on every request.
So the key model mirrors the entity model:
enroll()’s mode defaults to 'test' server-side, so a fresh enrollment can never touch live processing by accident. Pass mode: 'live' once you’re ready to charge real cards.
enroll() is not idempotent — call it once and store the secret. Every call mints a brand-new merchant key; it does not return or rotate a previous one. Calling it repeatedly doesn’t break anything (older keys keep working), but you pile up live credentials you then have to track and revoke. Treat key.secret like a password: persist it on first enroll, reuse it, and if you ever lose or leak one, revoke that key and enroll again. For narrower, disposable credentials, mint a per-TPA key with processing.tpas.keys.create(tpaId) instead.

Calling things more than once

Networks time out and retries happen, so it pays to know what each call does the second time. The rule of thumb: reads are safe to repeat, and every write here creates a new resource — none of them silently de-duplicate. Know which is which before you wrap anything in a retry loop.

Retry a charge safely

payments.process() is the one write you legitimately need to retry (timeouts mid-charge). Pass a stable idempotencyKey: the first call charges, any repeat with the same key returns that same payment instead of charging again.

Don’t re-submit an application

applications.create() has no server-side de-dup, so a retry creates a duplicate dossier. Keep your own “already applied?” guard, and once you have an id, poll instead of re-submitting:

Common errors


Next steps

Node SDK Quick Start

CRM setup — stores, products, funnels, payment flows

Partners — provision sub-merchants

If you onboard merchants on their behalf, use partners.processing.tpas.create() instead