Merchant automation (REST)
The Node SDK is the recommended path, but every partner operation is a plain HTTP call. This page is the route reference for backends in any language. All write calls require your Partner Key (tp_sk_partner_live_… / tp_sk_partner_test_…), minted in the Partner Hub.
The routes split along the platform’s two domains:
| Domain | Base URL | Provisions |
|---|
| CRM | https://api.tagada.io/api/public/v1/partner | merchants (acc_xxx) + CRM Keys (sk_crm_…) |
| Processing | https://api.tagada.io/api/tagadapay/v1/partner | TPAs (tpa_xxx) + Processing Keys (tp_sk_…) |
There is no cross-partner access — every call is scoped to your par_xxx.
Authentication
Authorization: Bearer tp_sk_partner_live_…
Only Partner Keys can provision merchants/TPAs or mint keys on their behalf. Scoped keys (CRM/Processing) cannot provision.
A test Partner Key can only mint test keys. Minting a live key with a test Partner Key returns 403 mode_escalation_forbidden.
CRM domain — merchants & CRM Keys
Base: /api/public/v1/partner
| Method | Path | Description |
|---|
POST | /merchants | Create a merchant (acc_xxx). CRM-only is valid. Idempotent on externalRef. |
GET | /merchants | List merchants. ?externalRef=… to look one up, ?limit=&cursor= to page. |
GET | /merchants/:accId | Retrieve a merchant. |
POST | /merchants/:accId/keys | Mint a CRM Key — token (sk_crm_…) returned once. |
GET | /merchants/:accId/keys | List CRM Keys (prefix only). |
DELETE | /keys/:keyId | Revoke a CRM Key. |
# Create a merchant
curl -X POST https://api.tagada.io/api/public/v1/partner/merchants \
-H "Authorization: Bearer tp_sk_partner_live_…" \
-H "Content-Type: application/json" \
-d '{ "legalName": "Acme SAS", "externalRef": "merchant_42", "country": "FR", "currency": "EUR" }'
# Mint a CRM Key for it
curl -X POST https://api.tagada.io/api/public/v1/partner/merchants/acc_xxx/keys \
-H "Authorization: Bearer tp_sk_partner_live_…"
# → { "object": "crm_key", "id": "…", "merchantId": "acc_xxx", "token": "sk_crm_live_…", ... }
Processing domain — TPAs & Processing Keys
Base: /api/tagadapay/v1/partner
| Method | Path | Description |
|---|
POST | /tpas | Create a TPA (merchantId in body). Idempotent on externalRef. |
GET | /tpas | List TPAs. ?merchantId=&externalRef=&limit=&cursor=. |
GET | /tpas/:tpaId | Retrieve a TPA. |
PATCH | /tpas/:tpaId | Re-point the TPA to another store of the same merchant ({ storeId }). Only mutation available. |
GET | /tpas/:tpaId/requirements | List KYB requirements. |
PATCH | /tpas/:tpaId/requirements/:code | Submit a value for a non-document requirement ({ value }). Flips it to pending_verification. |
GET | /tpas/:tpaId/documents | List KYB documents. |
POST | /tpas/:tpaId/documents | Record a KYB document (metadata). |
POST | /tpas/:tpaId/keys | Mint a Processing Key — secret (tp_sk_…) returned once. |
GET | /tpas/:tpaId/keys | List Processing Keys (prefix only). |
DELETE | /keys/:keyId | Revoke a Processing Key. |
# Create a TPA for an existing merchant
curl -X POST https://api.tagada.io/api/tagadapay/v1/partner/tpas \
-H "Authorization: Bearer tp_sk_partner_live_…" \
-H "Content-Type: application/json" \
-d '{ "merchantId": "acc_xxx", "externalRef": "merchant_42_eu", "country": "FR", "currency": "EUR" }'
# Mint a Processing Key for it
curl -X POST https://api.tagada.io/api/tagadapay/v1/partner/tpas/tpa_xxx/keys \
-H "Authorization: Bearer tp_sk_partner_live_…"
# → { "object": "processing_key", "id": "ak_xxx", "tpaId": "tpa_xxx", "secret": "tp_sk_live_…", ... }
Direct (non-partner) merchants use the same Processing routes without the /partner segment — e.g. POST /api/tagadapay/v1/tpas — authenticated with their own Processing Key. The /partner prefix is what marks an “on behalf of” call.
Target exists and belongs to you
Every mint/list/revoke validates the target before acting:
- The merchant/TPA exists — else
404 (merchant_not_found / tpa_not_found).
- It belongs to your partnership — else
403 (merchant_access_denied / tpa_access_denied).
You cannot mint keys for something you have not provisioned. Create it first, then mint on the returned id.
Common error responses
| HTTP | Code | When |
|---|
| 401 | missing_api_key | No Authorization: Bearer header |
| 401 | invalid_api_key | Unknown or revoked key |
| 403 | partner_scope_required | Not a Partner Key (e.g. a scoped key used to provision) |
| 403 | merchant_access_denied / tpa_access_denied | Target belongs to another partner |
| 403 | mode_escalation_forbidden | Test Partner Key minting a live key |
| 404 | merchant_not_found / tpa_not_found | Target id does not exist |
| 404 | api_key_not_found | Revoke target not found or already revoked |
Recommended partner-side mapping
your_merchants table:
external_ref → externalRef / Idempotency-Key on create
tagada_merchant_id → acc_xxx (CRM)
tagada_crm_key → encrypted sk_crm_live_…
tagada_tpa_id → tpa_xxx (Processing)
tagada_store_id → store_xxx
tagada_processing_key → encrypted tp_sk_live_…
Store secrets in your vault immediately — token/secret cannot be retrieved later.
End-to-end (SDK)
const partner = new Tagada(process.env.PARTNER_KEY!);
// 1. CRM: create the merchant + a CRM Key
const merchant = await partner.partners.crm.merchants.create({
legalName: 'Acme SAS',
externalRef: 'merchant_42',
});
const crmKey = await partner.partners.crm.merchants.keys.create(merchant.id);
// 2. Processing: create a TPA bound to that merchant + a Processing Key
const tpa = await partner.partners.processing.tpas.create({
merchantId: merchant.id,
externalRef: 'merchant_42_eu',
country: 'FR',
currency: 'EUR',
});
const processingKey = await partner.partners.processing.tpas.keys.create(tpa.id);
// 3. Persist on your side
await yourVault.put(merchant.externalRef ?? merchant.id, {
crmKey: crmKey.token,
processingKey: processingKey.secret,
storeId: tpa.storeId,
});
This is the pattern any embedded PSP, marketplace, or whitelabel partner should follow — not a one-off integration.