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.What you’re applying for: a TPA
Approval gives you a TagadaPay Account — a TPA (id prefixtpa_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:
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.
Minimal vs complete
- France (SEPA)
- United States (ACH)
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:
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:
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 fromrepresentative, 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:
issues: [] 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):
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
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:After approval: one key for all your TPAs
Once your applications are approved and their TPAs are provisioned, callenroll() 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.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.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