Core

Multi-merchant / multi-shop

Hierarchy of Merchant → Shop → API Key — when you need to pass `merchantId` / `shopId` on POST /payments and how rate limits / fees roll up.

Every account is structured as Merchant → Shop → API key pair. A merchant is the legal entity that signed the contract; a shop is an operational unit under that merchant (one URL, one brand, one payout config). Each shop has its own apiKey + secretKey pair, scoped to that shop. The vast majority of integrations are single-merchant + single-shop — but the hierarchy exists so SaaS platforms / marketplaces can fan transactions across multiple shops under one merchant, or multiple merchants under one operator account.

The hierarchy

text
Merchant (MCH-XXX)         ← legal entity, KYB on file, settlement payout config
  │
  ├─ Shop A (SHP-XXX)        ← brand A, paymentMethodIds[], methodFees{}
  │    ├─ pk_test_… / sk_test_…   (sandbox keys for Shop A)
  │    └─ pk_live_… / sk_live_…   (production keys for Shop A)
  │
  └─ Shop B (SHP-YYY)        ← brand B, different methods enabled, different fees
       ├─ pk_test_… / sk_test_…
       └─ pk_live_… / sk_live_…
A merchant can have N shops. Each shop is independent in terms of which payment methods are enabled, which fees apply, and which brand renders on hosted checkout. The merchant rolls up the balance — settlement happens at the merchant level, not per-shop.

API key scoping

Every API key (apiKey + secretKey pair) belongs to exactly ONE shop. When you authenticate with POST /api/v1/auth/token using a key pair, the resulting Bearer token is scoped to:

  • The owning shop — its paymentMethodIds drive what GET /payment-methods returns, and its methodFees determine charges.
  • The owning merchant — listed on GET /me as merchant.id.
bash
# A typical /me response — single merchant, single shop:
{
  "id": "MCH-ON-009",
  "name": "Golden Dragon",
  "industry": "money_services_business",
  "environment": "sandbox",
  "capabilities": { … }
}

The shopId is implicit in your auth token. You can confirm which shop your key resolved to via the shop field in the response of GET /payment-methods.

Routing a payment to a specific shop

If you use a per-shop key pair (the default), DON'T pass merchantId or shopId on POST /payments — they're inferred from the auth token. The fields exist on the schema as belt-and-suspenders: if you DO pass them, they must match the values resolved from the auth or the call is rejected with forbidden. This protects you from a key from Shop A accidentally charging Shop B.

json
// All of these work — same result:

// 1. Auth-implicit (recommended):
{ "amount": 50, "paymentMethodId": "1008", "country": "MEX" }

// 2. Explicit, must match auth:
{ "amount": 50, "paymentMethodId": "1008", "country": "MEX",
  "merchantId": "MCH-ON-009", "shopId": "SHP-MP1STV8W-832A" }

// 3. Mismatched → 403 forbidden:
{ "amount": 50, "paymentMethodId": "1008", "country": "MEX",
  "merchantId": "MCH-OTHER" }      // ← rejected, can't charge another merchant
We do NOT ship a "platform" API key that can fan-out across arbitrary merchants today. Every key is scoped. SaaS platforms aggregating multiple end-merchants should call our admin API to provision a separate merchant + shop per end-merchant, get keys, and use them per-merchant. Talk to support if you need a different model — we'll plan a platform-token feature if there's real demand.

Rate limits + billing

  • Rate limit is per-merchant by default (so a misbehaving shop doesn't starve siblings under the same merchant). See Rate limits.
  • Fee structure is per-shop (each shop has its own methodFees). The shop the key resolved to drives the fee charged on the transaction.
  • Settlement / payout happens at the merchant level. The merchant's configured wallet receives the aggregated balance across all shops, less platform + processor fees.