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
| Field | Tier | Notes |
|---|---|---|
businessName | Required | Legal entity name exactly as registered (or the person’s full name for a sole trader). |
country | Required | Country of registration — ISO 3166-1 alpha-2 (FR). |
activityType | Recommended | 'business' or 'individual'. Drives the acquirer legal-entity type. |
legalEntityType | Recommended | Canonical code: sas, sarl, sa, auto_entrepreneur, llc, ltd, inc, corporation… |
registrationNumber | Recommended | Company registration number from the registration certificate / KBIS. FR: SIREN/SIRET, UK: Companies House no., US: the 9-digit EIN (see note below). |
taxId | Recommended | Tax identifier. EU: the VAT number, e.g. FR00123456789. US: the federal EIN — the same value as registrationNumber. |
website | Recommended | Public URL — also used for the statement descriptor & content review. |
mcc | Recommended | Merchant Category Code, e.g. 5734. |
address | Recommended | Registered business address (street, city, postalCode recommended; apartment, state, country optional). |
email | Recommended | Business contact email (falls back to the representative’s). |
phone | Recommended | Business phone, E.164 (+33…). |
businessDescription | Optional | Plain-language description of what is sold. |
businessModel | Optional | One-liner, e.g. SaaS (subscription). |
desiredCurrencies | Optional | Settlement currencies — ISO 4217, e.g. ['EUR']. |
mccBreakdown | Optional | Per-MCC volume split ({ code, label?, volume?, averageTicket?, chargebackRatio?, refundRatio? }[]). |
monthlyVolume | Optional | Expected monthly card volume, major units as a string ('10000'). |
averageTicket | Optional | Typical order value, major units as a string. |
currentlyProcessing | Optional | boolean — already processing elsewhere today? |
currentProcessor | Optional | Current/previous processor name. |
previousMonthlyVolume | Optional | Volume processed elsewhere last month, as a string. |
expectedStartDate | Optional | ISO date YYYY-MM-DD. |
supportEmail / supportPhone | Optional | Customer-support contacts shown to cardholders. |
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.
| Field | Tier | Notes |
|---|---|---|
firstName | Required | Given name. |
lastName | Required | Family name. |
email | Required | Contact email — also where the confirmation is sent. |
phone | Recommended | E.164 (+33…). |
title | Recommended | Role: signatory, uboThroughOwnership, uboThroughControl, director… |
dateOfBirth | Recommended | ISO YYYY-MM-DD. |
nationality | Recommended | ISO 3166-1 alpha-2. |
idNumber | Recommended | Government ID number. |
idType | Recommended | passport · identityCard · driversLicense · nationalIdNumber. |
idCountry | Recommended | Issuing country — ISO 3166-1 alpha-2. |
idExpiry | Recommended | ISO YYYY-MM-DD. |
residentialAddress | Recommended | Home address (street, city, postalCode recommended) — not the business seat. |
idState | Optional | Issuing state/province, where relevant (US). |
ssnLast4 | Optional | Last 4 of SSN — US sole traders only. |
bankAccount
Settlement (payout) account. The account holder must match the legal entity — acquirers reject payouts to a mismatched name. Provide one rail.
| Field | Tier | Notes |
|---|---|---|
accountHolderName | Recommended | Must equal the legal entity name. |
currency | Recommended | Settlement currency — ISO 4217 (EUR). |
iban + bic | Recommended | SEPA rail. |
routingNumber + accountNumber | — | US ACH rail (use instead of IBAN). |
bsbNumber + accountNumber | — | Australian BSB rail. |
bankName / country | Optional | Bank name and country (ISO 3166-1 alpha-2). |
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:
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:| You have… | TPAs you’d open |
|---|---|
| Several legal entities (a holding with multiple LLCs, one company per brand) | One TPA per entity — each passes its own KYB |
| The same entity selling in several regions | One TPA per settlement region (e.g. an EU TPA settling in EUR, a US TPA settling in USD) |
| Risk or volume you want to split | Several TPAs so traffic and exposure spread across different acquirers |
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.| Key | Scope | Minted by | Sees |
|---|---|---|---|
CRM key (sk_crm_…) | the merchant | tagada-init / dashboard | CRM data + apply + enroll() |
Merchant processing key (tp_sk_…) | the merchant | processing.enroll() | all your TPAs |
Per-TPA key (tp_sk_…) | one TPA | processing.tpas.keys.create(tpaId) | that one TPA |
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.| Call | What it does | Safe to repeat? | A second call… |
|---|---|---|---|
processing.applications.create() | Submits a processing application | No | …files a second application in the review queue. Duplicates slow KYB and can provision an extra TPA. |
processing.enroll() | Mints your merchant processing key | No | …mints another live key. Old ones keep working — you just accumulate secrets to track and revoke. |
processing.tpas.keys.create() | Mints a per-TPA key | No | …mints another key. Great on purpose (one per service), a liability by accident. |
processing.tpas.list() / retrieve() | Reads your TPA(s) | Yes | …returns the same data. Repeat freely. |
payments.process() | Charges a card | Only with an idempotency key | …can double-charge without one; with a stable key it returns the original payment. |
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
| HTTP | Code | When |
|---|---|---|
| 400 | missing_required_fields | One of the 5 required fields is empty (missing lists them). |
| 400 | invalid_request | Body failed schema validation (issues has details). |
| 401 | invalid_api_key | Not a valid CRM key (sk_crm_…). |
| 403 | use_applications_api | A direct merchant tried tpas.create() — use this endpoint instead. |
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