import type { HttpClient } from '../HttpClient.js'; import type { RequestOptions } from '../types/common.js'; import type { Tpa, TpaCreateParams, SubMerchantCreateParams, TpaListParams, TpaProvisionParams, TpaProvisioning, ProcessingKey, ProcessingKeyCreated, ProcessingKeyCreateParams, TpaRequirement, RequirementValue, TpaDocument, TpaDocumentRecordParams, TpaDocumentUploadParams, Acquirer, OnboardingSession, OnboardingSessionCreateParams, ProcessingEnrollParams, ProcessingEnrollment, ProcessingApplication, ProcessingApplicationCreateParams, PartnerApplicationCreateParams, AuditDocumentParams, DocumentAuditResult, ProcessingListPage, ProcessingCharge, ChargeListParams, ProcessingDispute, DisputeListParams, ProcessingPayout, PayoutListParams, ProcessingBalanceTransaction, BalanceTransactionListParams, ProcessingChargebackAlert, ChargebackAlertListParams, ProcessingMarkupGrid, TpaMarkup, TpaPayoutParams, TpaPayoutRun, TpaPayoutSchedule, TpaPayoutScheduleParams, ProcessingBalance, BalanceRetrieveParams, AcquiringRouteList, AcquiringRouteEnabled, PayoutInstrument, TpaBankAccountCreateParams, TpaBankingOverview, ProcessingChargeDetail, ChargeRetrieveParams, ChargeRefundParams, ChargeRefundResult, ProcessingRefund, RefundListParams, DisputeRetrieveParams, DisputeSubmitEvidenceParams, DisputeAcceptParams, DisputeActionResult, TpaStats, TpaStatsParams, ProcessingWebhookEndpoint, ProcessingWebhookEndpointCreateParams, ProcessingWebhookEndpointUpdateParams, ProcessingWebhookEndpointListParams, ProcessingWebhookDelivery, ProcessingWebhookDeliveryListParams } from '../types/partners.js'; /** * Processing domain (TagadaPay Processing), served on `/api/tagadapay/v1`. * * The same resource classes back two SDK entry points, differing only by a * URL prefix: * - `tagada.processing.*` → direct merchant, prefix `''` * - `tagada.partners.processing.*` → partner "on behalf of", prefix `/partner` * * Auth is always a Processing / partner API key (`tp_sk_…`). This namespace * does **not** cover Hub Ops (`/api/v2/ops/*`), which is Clerk-session * `payment_ops` IAM (Job × Scope) — see mintlify IAM Overview. */ /** Processing keys (`tp_sk_…`), each scoped to one TPA. */ export declare class ProcessingKeys { private readonly client; private readonly prefix; constructor(client: HttpClient, prefix: string); /** * Mint a processing key restricted to one TPA. The plaintext `secret` is * returned ONLY on creation — store it immediately in your secret manager. */ create(tpaId: string, params?: ProcessingKeyCreateParams, opts?: RequestOptions): Promise; list(tpaId: string, opts?: RequestOptions): Promise<{ data: ProcessingKey[]; }>; /** Revoke a processing key. Subsequent calls with that secret get HTTP 401. */ revoke(keyId: string, opts?: RequestOptions): Promise<{ id: string; status: 'revoked'; }>; } /** KYB requirements for a TPA. */ export declare class ProcessingRequirements { private readonly client; private readonly prefix; constructor(client: HttpClient, prefix: string); list(tpaId: string, opts?: RequestOptions): Promise<{ data: TpaRequirement[]; }>; /** * Submit a value for a non-document requirement (e.g. `business.vat_number`, * `banking.iban`). The requirement flips to `pending_verification` — it is * never set directly to `satisfied` (Tagada ops / a provider verify it). * Document requirements are satisfied via `documents.record()` instead. */ update(tpaId: string, code: string, value: RequirementValue, opts?: RequestOptions): Promise; } /** * KYB documents for a TPA. Two paths: * * - `upload()` — send the raw bytes (multipart). Most reliable: nothing to * keep alive on your side. * - `record()` — reference a `storageUrl`. The URL must be fetchable * server-to-server AT RECORD TIME (fresh presigned URL is fine — Tagada * downloads and pins a copy immediately); unreachable URLs are rejected * with `422 document_unreachable`. * * After provisioning runs, check `list()`: a document that could not be * delivered to the payment processor shows `status: 'rejected'` with a * `rejectionReason` explaining what to fix. */ export declare class ProcessingDocuments { private readonly client; private readonly prefix; constructor(client: HttpClient, prefix: string); list(tpaId: string, opts?: RequestOptions): Promise<{ data: TpaDocument[]; }>; /** * Record a document by `storageUrl`. Tagada downloads the file immediately * and stores its own copy, so the URL only needs to be valid at call time * (a fresh presigned URL works; later expiry is fine). Rejects with * `422 document_unreachable` when the URL can't be fetched — in that case * prefer `upload()` with the raw bytes. */ record(tpaId: string, params: TpaDocumentRecordParams, opts?: RequestOptions): Promise; /** * Upload a KYB document's raw bytes AND record it in one call — the * programmatic equivalent of a merchant dropping a file on the onboarding * form. Tagada stores the file and links it to the TPA (and, when * `requirementCode` is given, flips that `documents.*` requirement to * `pending_verification`). * * `file` is a `Blob` (Node 18+ exposes `Blob` and `FormData` globally; use * `new Blob([buffer])` or a `File`). Allowed: PDF, JPG, PNG, WEBP, HEIC, * up to 10MB. * * @example * import { readFile } from 'node:fs/promises'; * const bytes = await readFile('./registration.pdf'); * await tagada.partners.processing.tpas.documents.upload(tpaId, { * file: new Blob([bytes], { type: 'application/pdf' }), * filename: 'registration.pdf', * kind: 'company_registration', * requirementCode: 'documents.company_registration', * }); */ upload(tpaId: string, params: TpaDocumentUploadParams, opts?: RequestOptions): Promise; } /** * Acquirers a partner has signed and may use. Partner surface only — * served on `/api/tagadapay/v1/partner/acquirers`. */ export declare class ProcessingAcquirers { private readonly client; private readonly prefix; constructor(client: HttpClient, prefix: string); /** * List the acquirers this partner has signed, with per-acquirer * economics (buy rate, the partner's markup, resulting sell rate) and * operational carve-outs. Use an entry's `name` to pin a TPA: * `tpas.create({ acquirer })`. * * @example * const acquirers = await tagada.partners.processing.acquirers.list(); * // [{ name: 'adyen', sellRate: {...}, ... }, ...] */ list(opts?: RequestOptions): Promise<{ data: Acquirer[]; }>; } /** * Partner embed onboarding — mint an iframe session for the KYB form. * Partner surface only (`/api/tagadapay/v1/partner/onboarding/sessions`). */ export declare class PartnerProcessingOnboarding { private readonly client; private readonly prefix; constructor(client: HttpClient, prefix: string); /** * Create (or resume) a short-lived embed session. Mount `session.url` in an * iframe — see [Embed onboarding](https://docs.tagada.io/developer-tools/partners/embed-onboarding). * Durable resume key is `session.entityId` (pass it back as `entityId`, or reuse * the same `externalRef`). Mid-form progress is stored on that entity — same * contract as the Tagada dashboard form / abandoned-recovery emails. */ createSession(params: OnboardingSessionCreateParams, opts?: RequestOptions): Promise; } /** * TagadaPay Accounts (TPAs) — the processing **read / manage** surface. * A merchant (`acc_xxx`) can own multiple TPAs (`tpa_xxx`). * * This base class never creates a TPA. Direct merchants do not provision * TPAs: they submit an application via `tagada.processing.applications.create()` * and our team creates + assigns the TPA. Once assigned, use these methods * (plus `keys` / `requirements` / `documents`) to manage and charge on it. * * Partners provision on behalf of merchants via * `tagada.partners.processing.tpas.create()` — see {@link PartnerProcessingTpas}. */ export declare class ProcessingTpas { protected readonly client: HttpClient; protected readonly prefix: string; readonly keys: ProcessingKeys; readonly requirements: ProcessingRequirements; readonly documents: ProcessingDocuments; constructor(client: HttpClient, prefix: string); retrieve(tpaId: string, opts?: RequestOptions): Promise; /** Look up a TPA by your own external reference. Returns `null` if none match. */ retrieveByExternalRef(externalRef: string, opts?: RequestOptions): Promise; list(params?: TpaListParams, opts?: RequestOptions): Promise<{ data: Tpa[]; hasMore: boolean; }>; /** * Kick provisioning ("go live"). **This call is mandatory** — creating the * TPA and uploading documents queues everything on Tagada's side, but * NOTHING is sent to the acquirer until you call `provision()`. A TPA that * never gets this call stays `pending_provisioning` forever. * * Call it once every requirement is filled (including the `banking.*` * codes — without a bank account, payouts can never be configured) and * every KYB document is uploaded. It runs the full activation pipeline * against the acquirer assigned to the TPA (create account → push merchant * data → upload documents). * * An acquirer must already be assigned (via your auto-router default or by * Tagada). Otherwise the call fails with `412 no_acquirer_assigned`. * * Idempotent: re-calling is always safe — completed steps are reused, only * what is missing or changed is replayed. Treat it as "converge toward * active": fix what the response points at, call again. * * **Contract signature is mandatory (live mode).** Once provisioning * completes, a Merchant Service Agreement — co-branded with your partner * branding — is emailed automatically to the merchant representative * (`representative.email`). The TPA stays `pending_provisioning` until it is * signed, then activates automatically. Check `result.contract`: relay * `signingUrl` to your merchant to speed things up. Test-mode TPAs and MoR * sub-merchants are exempt. * * @example * // 1. fill requirements (incl. banking.*) + upload documents, then: * const result = await tagada.partners.processing.tpas.provision(tpaId); * if (!result.completed) { * console.log(result.nextAction); // one-line "what to do next" * console.log(result.requirements.dueCodes); // e.g. ['banking.iban', …] * console.log(result.rejectedDocuments); // docs that failed delivery + why * } * if (result.contract?.status === 'pending_signature') { * console.log(result.contract.signingUrl); // send this to the merchant * } * // …fix, re-upload, then simply call provision(tpaId) again. */ provision(tpaId: string, params?: TpaProvisionParams, opts?: RequestOptions): Promise; /** * Trigger an immediate payout of the TPA's available balance (minus rolling * reserve and outstanding debt) to its registered bank account. Pass * `amountMinor` for a partial payout — it is always clamped to the safe * maximum, so you can never over-withdraw. * * Requires a verified bank account on the TPA. MoR sub-merchants share the * root TPA's balance: trigger the payout on the ROOT TPA (a child returns * `skipped: true, reason: 'sub_merchant_parent_settles'`). * * When no payout is possible the call returns `409` with the run envelope * (`skipped: true` + `reason`), e.g. `below_minimum` (< 1.00 available). * * @example * const run = await tagada.partners.processing.tpas.payout('tpa_your_root'); * if (!run.skipped) console.log(`paid ${run.amountMinor} — ${run.payoutId}`); */ payout(tpaId: string, params?: TpaPayoutParams, opts?: RequestOptions): Promise; /** * Read the Tagada cron payout mode for a root TPA. * `automatic` = daily Tagada sweep; `manual` = funds accumulate until * {@link payout}. Never reflects Adyen/Stripe native schedules (those stay off). * * MoR: call on the ROOT TPA — children return `409 sub_merchant_parent_settles`. * * @example * const schedule = await tagada.partners.processing.tpas.getPayoutSchedule('tpa_your_root'); * // schedule.mode === 'automatic' | 'manual' */ getPayoutSchedule(tpaId: string, opts?: RequestOptions): Promise; /** * Set the Tagada cron payout mode for a merchant TPA. Does **not** enable * Adyen bank push sweeps or Stripe Connect automatic payouts — only our * cron (or {@link payout}). * * @example * // Stop daily auto cash-out; pay out yourself when ready: * await tagada.partners.processing.tpas.setPayoutSchedule('tpa_your_root', { * mode: 'manual', * }); * // Re-enable daily Tagada cron: * await tagada.partners.processing.tpas.setPayoutSchedule('tpa_your_root', { * mode: 'automatic', * }); */ setPayoutSchedule(tpaId: string, params: TpaPayoutScheduleParams, opts?: RequestOptions): Promise; /** * List the TPA's acquiring routes — which acquiring account each charge * currency goes through, and therefore **which currency it settles in**. * Every TPA has a default route (its home currency); extra routes added * with `enableRoute()` remove FX at settlement for those currencies. */ listRoutes(tpaId: string, opts?: RequestOptions): Promise; /** * Enable an acquiring route for a currency: from the next charge on, * charges in that currency settle in that currency — no FX. Idempotent * (re-enabling an existing route returns it with `created: false`). * * Applies to new charges only; refunds/captures of past charges keep the * route the original payment used. If no acquiring account settles the * requested currency the call fails with `422 * no_merchant_account_for_currency` and charges keep using the default * route (converted at settlement). * * @example * // EUR charges settle in EUR from now on: * const route = await tagada.partners.processing.tpas.enableRoute('tpa_xxx', 'EUR'); * console.log(route.acquiringAccount, route.created); */ enableRoute(tpaId: string, currency: string, opts?: RequestOptions): Promise; /** * List the TPA's registered payout bank accounts (masked): one per * currency, plus an optional catch-all. Use it to check which currencies * are covered before calling `payout()` — a payout in a currency with no * active bank account is refused. * * MoR sub-merchants return an empty list — funds pool on the partner's * ROOT TPA, which holds the accounts. * * @example * const banking = await tagada.partners.processing.tpas.getBanking('tpa_your_root'); * const covered = banking.instruments.filter((i) => i.status === 'active').map((i) => i.currency); */ getBanking(tpaId: string, opts?: RequestOptions): Promise; /** * Register a payout bank account for a currency, self-serve. One account * per currency: each settled currency sweeps to the bank account in that * currency without FX. Complements {@link enableRoute}: the route makes a * currency SETTLE natively, the bank account makes it PAY OUT natively. * * The account is created `pending` and flips to `active` automatically * once the acquirer verifies the bank belongs to the TPA's legal entity * (`holderName` must match). Poll `getBanking()` to track it. * * Adding an account for a NEW currency is self-serve; REPLACING an * existing one is deliberately not (`409 bank_account_exists`) — bank * swaps are the classic payout-fraud vector and stay ops-reviewed. * MoR sub-merchants: register on the partner's ROOT TPA * (`409 mor_sub_merchant_banking` otherwise). * * @example * // US account for the USD balance: * await tagada.partners.processing.tpas.createBankAccount('tpa_your_root', { * currency: 'USD', * bankAccount: { * accountNumber: '000123456789', * routingNumber: '021000021', * holderName: 'Acme Inc.', // must match the legal entity * accountType: 'checking', * country: 'US', * }, * }); * // EUR IBAN for the EUR balance (after enableRoute('EUR')): * await tagada.partners.processing.tpas.createBankAccount('tpa_your_root', { * currency: 'EUR', * bankAccount: { iban: 'FR76…', holderName: 'Acme Inc.' }, * }); */ createBankAccount(tpaId: string, params: TpaBankAccountCreateParams, opts?: RequestOptions): Promise; /** * Windowed processing KPIs for the TPA: gross volume and counts by outcome * (succeeded / refunded / failed / disputed), total fees, authorization * rate (basis points), average ticket, and a daily gross series for * charting. Defaults to the last 30 days (`days`: 1–365). * * @example * const stats = await tagada.partners.processing.tpas.getStats('tpa_xxx', { days: 7 }); * console.log(`auth rate: ${(stats.authRateBps ?? 0) / 100}%`); * console.log(`avg ticket: ${stats.averageTicketMinor} minor ${stats.currency}`); */ getStats(tpaId: string, params?: TpaStatsParams, opts?: RequestOptions): Promise; } /** * Partner TPA surface — everything in {@link ProcessingTpas} plus `create`. * Only **payfac white-label** partners (`subscribed_products` includes `payfac`) * may call `create`. CRM-only partners must use * {@link PartnerProcessingApplications.create} or embed onboarding instead — * the API returns `403 payfac_required` otherwise. * * Direct merchants use `tagada.processing.applications.create()` instead. */ export declare class PartnerProcessingTpas extends ProcessingTpas { /** * Create a new TPA on behalf of a sub-merchant. **Payfac partners only.** * * Pass `accountId` to attach it to an existing merchant. Pass `externalRef` * for idempotency. * * **Who assigns the acquirer** depends on your partner situation: * * - **Processing partner** (you have signed acquirers — `acquirers.list()` * is non-empty): pass `acquirer` to pin one yourself, or omit it to let * Tagada's router pick from your signed set. The TPA moves to * `pending_provisioning` and you self-serve to `active`. * - **CRM-only partner** (`subscribed_products` has `crm` but not `payfac`): * do **not** call this — use `partners.processing.applications.create({ * accountId, businessInfo, … })` (same payload as merchant * [processing-applications](https://docs.tagada.io/developer-tools/node-sdk/processing-applications)) * or embed `onboarding.createSession`. Calling `tpas.create` returns * `403 payfac_required`. * * **Creating the TPA is step 1 of 4** — it does not go live until you * complete the sequence (also returned as `nextSteps` on the response): * fill the requirements (including `banking.*`), upload the KYB documents, * then **call `tpas.provision(id)`** — nothing is sent to the acquirer * until you do — and check its response (`nextAction`, * `requirements.dueCodes`, `rejectedDocuments`) to converge to `active`. * * @example * const tpa = await tagada.partners.processing.tpas.create({ * legalName: 'Acme SAS', * accountId: 'acc_xxx', * country: 'FR', currency: 'EUR', * externalRef: 'merchant_42_eu', * acquirer: 'adyen', * }); * await tagada.partners.processing.tpas.provision(tpa.id); */ create(params: TpaCreateParams, opts?: RequestOptions): Promise; /** * Read a merchant's pricing configuration: the per-TPA markup (if any), * whether it or your partner-level grid applies (`source`), and the * resolved charge-time `sellRate` (Tagada buy rate + effective markup). */ retrieveMarkup(tpaId: string, opts?: RequestOptions): Promise; /** * Set this merchant's markup — YOUR margin on top of Tagada's buy rate for * THIS merchant only. Replaces your partner-level markup grid wholesale for * the TPA (pass `{}` to sell at buy rate, i.e. zero margin). All fields are * additive and must be >= 0 — you can never price below Tagada's cost. * * Takes effect immediately: the TPA's charge-time price snapshot is * refreshed as part of the call. * * @example * await tagada.partners.processing.tpas.updateMarkup('tpa_xxx', { * cardMarkupBps: 100, // +1.00% for you * cardFixedCents: 10, // +$0.10 for you * }); */ updateMarkup(tpaId: string, markup: ProcessingMarkupGrid, opts?: RequestOptions): Promise; /** * Remove the per-TPA markup — the merchant reverts to your partner-level * markup grid. Takes effect immediately. */ clearMarkup(tpaId: string, opts?: RequestOptions): Promise; } /** * Partner Merchant-of-Record **sub-merchants** — provision sub-merchants that * run under YOUR payfac umbrella (shared Adyen account holder + settlement * balance account), each with its own store + statement descriptor. * * This is a distinct lifecycle from {@link PartnerProcessingTpas.create}: * - `tpas.create()` → full KYB tree, requires `provision()` to go live. * - `subMerchants.create()` → **no KYB pipeline, returned `active`**, funds * settle into YOUR balance account (you redistribute off-platform). * * Requires the MoR sub-merchant system to be enabled for your partner * (ask your account manager). */ export declare class PartnerProcessingSubMerchants { private readonly client; private readonly prefix; constructor(client: HttpClient, prefix: string); /** * Provision a MoR sub-merchant under your partner umbrella. Returns the * sub-merchant's TPA (`payfacMode: 'mor'`, `parentTpaId` set), **already * `active`** — mint a processing key on it and charge immediately. * * @example * // 1. Give the sub-merchant its own CRM account * const acc = await tagada.partners.crm.merchants.create({ * legalName: 'Boutique Zoé', externalRef: 'zoe', * }); * // 2. Provision the sub-merchant under your MoR root TPA * const sub = await tagada.partners.processing.subMerchants.create({ * parentTpaId: 'tpa_your_root', // omit to use your default MoR root * accountId: acc.id, * legalName: 'Boutique Zoé', * statementDescriptor: 'ZOE PARIS', // ≤ 22 chars, on the cardholder statement * webAddress: 'https://zoe.example', * externalRef: 'zoe', * }); * // 3. Charge on it right away — no provision()/KYB step * const key = await tagada.partners.processing.tpas.keys.create(sub.id); */ create(params: SubMerchantCreateParams, opts?: RequestOptions): Promise; } /** Charges (attempts + captures) for a TPA. `processing.charges.list()`. */ export declare class ProcessingCharges { private readonly client; constructor(client: HttpClient); /** * List charges for a TPA, newest first. * * @example * const page = await tagada.processing.charges.list({ account: 'tpa_xxx', limit: 50 }); * for (const charge of page.data) console.log(charge.id, charge.amountMinor); * if (page.hasMore) { * const next = await tagada.processing.charges.list({ account: 'tpa_xxx', cursor: page.nextCursor! }); * } */ list(params: ChargeListParams, opts?: RequestOptions): Promise>; /** * Retrieve one charge with the full detail the list omits: payment method * and scheme variant, 3DS outcome, auth code, billing country, cumulative * refunded amount, and the Tagada CRM ids (order / customer / payment). * * @example * const charge = await tagada.processing.charges.retrieve('psp_ref', { account: 'tpa_xxx' }); * const refundable = charge.amountMinor - charge.refundedAmountMinor; */ retrieve(chargeId: string, params: ChargeRetrieveParams, opts?: RequestOptions): Promise; /** * Refund a charge (full or partial) through the TPA's acquirer — the same * engine as the dashboard refund. Omit `amountMinor` to refund the whole * remaining amount; the call is rejected if it exceeds what is refundable. * * The response confirms the provider ACCEPTED the refund; the confirmed * refund row lands in `refunds.list()` once the provider's webhook fires. * * @example * await tagada.processing.charges.refund('psp_ref', { * account: 'tpa_xxx', * amountMinor: 500, // €5.00 partial — omit for full refund * }); */ refund(chargeId: string, params: ChargeRefundParams, opts?: RequestOptions): Promise; } /** Confirmed refunds for a TPA. `processing.refunds.list()`. */ export declare class ProcessingRefunds { private readonly client; constructor(client: HttpClient); /** * List refunds, newest first. Rows appear once the acquirer confirms the * refund (webhook-backfilled) — a refund you just issued with * `charges.refund()` can take a moment to show up. Filter with `charge` * to get all refunds of one charge. */ list(params: RefundListParams, opts?: RequestOptions): Promise>; } /** Disputes / chargebacks for a TPA. `processing.disputes.list()`. */ export declare class ProcessingDisputes { private readonly client; constructor(client: HttpClient); list(params: DisputeListParams, opts?: RequestOptions): Promise>; /** Retrieve one dispute by id (reason, status, deadline, linked charge). */ retrieve(disputeId: string, params: DisputeRetrieveParams, opts?: RequestOptions): Promise; /** * Contest a dispute by submitting evidence to the acquirer. Text fields * and inline base64 files (max 5 × 4MB; PDF/JPEG/PNG — Adyen rejects PNG * and caps PDFs at 2MB). One-shot on Adyen/Tilled; Stripe also supports * drafts (`submit: false`). * * Watch `evidenceDueBy` on the dispute — after the deadline the dispute is * lost automatically. * * @example * import { readFile } from 'node:fs/promises'; * const receipt = await readFile('./receipt.pdf'); * await tagada.processing.disputes.submitEvidence('dp_xxx', { * account: 'tpa_xxx', * evidence: { * productDescription: 'Monthly subscription, delivered by email', * customerEmailAddress: 'buyer@example.com', * files: [{ * slot: 'receipt', * name: 'receipt.pdf', * contentType: 'application/pdf', * contentBase64: receipt.toString('base64'), * }], * }, * }); */ submitEvidence(disputeId: string, params: DisputeSubmitEvidenceParams, opts?: RequestOptions): Promise; /** * Concede the dispute (accept liability). Supported on Stripe and Adyen; * on Tilled a dispute is conceded by simply not responding before the * deadline (this call returns 422 there). */ accept(disputeId: string, params: DisputeAcceptParams, opts?: RequestOptions): Promise; } /** Payouts (settlements to the merchant's bank) for a TPA. `processing.payouts.list()`. */ export declare class ProcessingPayouts { private readonly client; constructor(client: HttpClient); list(params: PayoutListParams, opts?: RequestOptions): Promise>; } /** Balance-ledger entries for a TPA. `processing.balanceTransactions.list()`. */ export declare class ProcessingBalanceTransactions { private readonly client; constructor(client: HttpClient); list(params: BalanceTransactionListParams, opts?: RequestOptions): Promise>; } /** Live provider balance for a TPA. `processing.balance.retrieve({ account })`. */ export declare class ProcessingBalanceResource { private readonly client; constructor(client: HttpClient); /** * Retrieve the TPA's balance **live from the acquirer** (Stripe * `balance.retrieve` / Adyen Balance Platform) — one bucket per currency, * in minor units. This is the real-time figure; for the historical ledger * use `balanceTransactions.list()`. * * Merchant-of-Record sub-merchants don't own a balance: their funds settle * into the root TPA's shared balance account. Querying a sub-merchant * returns the SHARED root balance (`shared: true`, `heldBy` = root TPA) and * requires a key authorized for that root TPA (e.g. your partner key) — * a key scoped to the sub-merchant alone gets a 403. * * @example * const balance = await tagada.partners.processing.balance.retrieve({ account: 'tpa_xxx' }); * for (const b of balance.balances) { * console.log(`${b.currency}: available ${b.availableMinor}, pending ${b.pendingMinor}`); * } */ retrieve(params: BalanceRetrieveParams, opts?: RequestOptions): Promise; } /** Pre-dispute chargeback alerts (Ethoca/RDR/…) for a TPA. `processing.chargebackAlerts.list()`. */ export declare class ProcessingChargebackAlerts { private readonly client; constructor(client: HttpClient); list(params: ChargebackAlertListParams, opts?: RequestOptions): Promise>; } /** * Aggregates the TPA-scoped processing **read** resources. Shared by the * direct (`tagada.processing`) and partner (`tagada.partners.processing`) * namespaces — the endpoints carry no `/partner` prefix; per-TPA * authorization is derived from the key's scope server-side. */ /** * Delivery log + replay for one webhook endpoint * (`webhookEndpoints.deliveries.list(endpointId)`, `.replay()`). */ export declare class ProcessingWebhookDeliveries { private readonly client; constructor(client: HttpClient); /** * List deliveries for an endpoint, newest first. Filter with * `status: 'failed'` to find events your endpoint missed. * * @example * const { data } = await tagada.processing.webhookEndpoints.deliveries.list('we_xxx', { * status: 'failed', * }); */ list(endpointId: string, params?: ProcessingWebhookDeliveryListParams, opts?: RequestOptions): Promise>; /** * Re-send a delivery's exact original payload as a fresh delivery (the * historical row is preserved). Works for succeeded and failed deliveries. */ replay(endpointId: string, deliveryId: string, opts?: RequestOptions): Promise; } /** * Webhook endpoint subscriptions on the processing plane. * * Events are signed (`tagadapay-signature: t=…,v1=…`) with the endpoint's * `whsec_…` secret — verify with `constructProcessingEvent()` (exported at * the package root). Partner endpoints receive events for ALL the partner's * TPAs; `event.account` carries the TPA id. * * @example * const endpoint = await tagada.partners.processing.webhookEndpoints.create({ * url: 'https://example.com/webhooks/tagada', * enabledEvents: ['payout.*', 'dispute.*', 'charge.failed'], * }); * console.log(endpoint.secret); // whsec_… — store it to verify signatures */ export declare class ProcessingWebhookEndpoints { private readonly client; /** Delivery log + replay (`deliveries.list(endpointId)`, `.replay()`). */ readonly deliveries: ProcessingWebhookDeliveries; constructor(client: HttpClient); /** * Create an endpoint. Owner defaults by key scope: a partner key creates a * partner-level endpoint, a TPA-restricted key creates that TPA's merchant * endpoint. Pass `ownerType`/`ownerId` to be explicit. */ create(params: ProcessingWebhookEndpointCreateParams, opts?: RequestOptions): Promise; /** List endpoints (owner inferred from the key scope when omitted). */ list(params?: ProcessingWebhookEndpointListParams, opts?: RequestOptions): Promise>; retrieve(id: string, opts?: RequestOptions): Promise; /** Update url / subscribed events, or enable/disable delivery. */ update(id: string, params: ProcessingWebhookEndpointUpdateParams, opts?: RequestOptions): Promise; del(id: string, opts?: RequestOptions): Promise; } export declare class ProcessingReads { readonly charges: ProcessingCharges; readonly refunds: ProcessingRefunds; readonly disputes: ProcessingDisputes; readonly payouts: ProcessingPayouts; readonly balance: ProcessingBalanceResource; readonly balanceTransactions: ProcessingBalanceTransactions; readonly chargebackAlerts: ProcessingChargebackAlerts; constructor(client: HttpClient); } /** * Partner applications — same KYB payload as merchant * {@link ProcessingApplications}, scoped to a sub-merchant `accountId`. * Preferred intake for CRM-only partners (lands in Entity Inbox, no TPA until * Tagada promotes). * * @see https://docs.tagada.io/developer-tools/node-sdk/processing-applications */ export declare class PartnerProcessingApplications { private readonly client; private readonly prefix; constructor(client: HttpClient, prefix: string); /** * One-shot submit for a sub-merchant. Same side effects as * `processing.applications.create()` (KYC flip, doc ingest, inbox). * * @example * const app = await partner.partners.processing.applications.create({ * accountId: 'acc_xxx', * businessInfo: { businessName: 'Sndnow LLC', country: 'US', mcc: '5999' }, * representative: { firstName: 'Jon', lastName: 'Reyes', email: 'jon@example.com' }, * }); */ create(params: PartnerApplicationCreateParams, opts?: RequestOptions): Promise; retrieve(id: string, opts?: RequestOptions): Promise; auditDocument(params: AuditDocumentParams, opts?: RequestOptions): Promise; } /** * Merchant application intake — the self-serve onboarding path. This is THE * way a direct merchant asks TagadaPay to process their cards. Authenticate * with a **CRM key** (`sk_crm_…`); no processing key or enroll step is * involved. * * The payload mirrors the dashboard "New Request" form 1:1 and is the same * data acquirers run KYB/KYC on. See {@link ProcessingApplicationCreateParams} * — every field is tagged Required / Recommended / Optional, and your editor * will autocomplete the full set. * * @see https://docs.tagada.io/developer-tools/node-sdk/processing-applications */ export declare class ProcessingApplications { private readonly client; constructor(client: HttpClient); /** * One-shot submit: registers the application with the same side effects as * the dashboard New Request form (KYC flip, doc ingest, confirmation email) * and lands it in TagadaPay's review queue. * * Only `businessName` + `country` + the representative's `firstName` / * `lastName` / `email` are strictly required. Everything tagged * *Recommended* in {@link ProcessingApplicationCreateParams} is verified by * acquirers before activation — omitting it doesn't fail the call, but the * response echoes the gaps in `recommendations` and the review queue * flags them. Send a complete application to get approved faster. * * @example * const crm = new Tagada({ apiKey: process.env.TAGADA_CRM_KEY }); * * const application = await crm.processing.applications.create({ * businessInfo: { * // ── Required ── * businessName: 'PLATANE GROUP', * country: 'FR', * // ── Recommended (acquirer KYB) ── * activityType: 'business', * legalEntityType: 'sas', * registrationNumber: '977653740', // SIREN / company number * taxId: 'FR71977653740', // VAT * website: 'https://platane.app', * mcc: '5734', * email: 'ops@platane.app', * phone: '+33625898229', * address: { street: '312 Impasse de la Carrière', city: 'Romagnieu', postalCode: '38480', country: 'FR' }, * // ── Optional (risk profile) ── * businessModel: 'SaaS (subscription)', * monthlyVolume: '10000', * desiredCurrencies: ['EUR'], * }, * representative: { * // ── Required ── * firstName: 'Loïc', * lastName: 'Delobel', * email: 'loic@platane.app', * // ── Recommended (KYC) ── * phone: '+33625898229', * title: 'signatory', * dateOfBirth: '1995-07-21', * nationality: 'FR', * idType: 'identityCard', * idNumber: 'C7C8H20W1', * idCountry: 'FR', * idExpiry: '2031-09-12', * residentialAddress: { street: '33 Rue de la Charité', city: 'Lyon', postalCode: '69002', country: 'FR' }, * }, * // ── Recommended: settlement account (holder MUST match the entity) ── * bankAccount: { * accountHolderName: 'SAS PLATANE GROUP', * iban: 'FR7640978000532127018221051', * bic: 'BSPFFRPPXXX', * currency: 'EUR', * country: 'FR', * }, * }); * * // Non-blocking KYB gaps you can still fill via the dashboard: * if (application.recommendations?.length) { * console.warn('Recommended fields still missing:', application.recommendations); * } */ create(params: ProcessingApplicationCreateParams, opts?: RequestOptions): Promise; /** Poll application status. Scoped to the CRM account that owns the key. */ retrieve(id: string, opts?: RequestOptions): Promise; /** * Pre-submission coherence check for a single already-uploaded document. * * Compares the file against the declared `businessInfo` / `representative` * (the same data you pass to `create`) and returns advisory, non-blocking * findings — wrong document type, name/country/number mismatch, missing * field. Run it right after uploading each document so you can fix * inconsistencies BEFORE submitting and maximise direct Adyen acceptance. * * Best-effort: an unreadable file or an unavailable analyzer returns * `{ issues: [], source: 'none' }` rather than throwing. * * @example * const audit = await crm.processing.applications.auditDocument({ * kind: 'passport', * fileUrl: uploadedUrl, * representative: { firstName: 'Loïc', lastName: 'Delobel', nationality: 'FR' }, * }); * if (audit.issues.length) { * for (const i of audit.issues) console.warn(`[${i.code}] ${i.message} — ${i.suggestion ?? ''}`); * } */ auditDocument(params: AuditDocumentParams, opts?: RequestOptions): Promise; } /** * Top-level processing namespace exposed as `tagada.processing`. For a direct * merchant who: * 1. submits an application with `applications.create()` (CRM key), then * 2. once our team has created + assigned their TPA, manages and charges * on it via `tpas.*` (with a processing key from `enroll()`). * * Direct merchants never create a TPA — that is partner-only * (`tagada.partners.processing.tpas.create()`). */ export declare class Processing { private readonly client; readonly tpas: ProcessingTpas; readonly applications: ProcessingApplications; /** Charges for a TPA (`processing.charges.list({ account })`, `.retrieve()`, `.refund()`). */ readonly charges: ProcessingCharges; /** Confirmed refunds for a TPA (`processing.refunds.list({ account })`). */ readonly refunds: ProcessingRefunds; /** Disputes for a TPA (`processing.disputes.list({ account })`, `.retrieve()`, `.submitEvidence()`, `.accept()`). */ readonly disputes: ProcessingDisputes; /** Payouts for a TPA (`processing.payouts.list({ account })`). */ readonly payouts: ProcessingPayouts; /** Live provider balance for a TPA (`processing.balance.retrieve({ account })`). */ readonly balance: ProcessingBalanceResource; /** Balance-ledger entries for a TPA (`processing.balanceTransactions.list({ account })`). */ readonly balanceTransactions: ProcessingBalanceTransactions; /** Pre-dispute chargeback alerts for a TPA (`processing.chargebackAlerts.list({ account })`). */ readonly chargebackAlerts: ProcessingChargebackAlerts; /** Webhook endpoints + delivery log/replay (`processing.webhookEndpoints.*`). */ readonly webhookEndpoints: ProcessingWebhookEndpoints; constructor(client: HttpClient); /** * Enroll the authenticated CRM account for processing — the * CRM → Processing bridge. Call this on a client built with your **CRM * key** (`sk_crm_…`). It mints and returns a merchant-scoped processing * key (`tp_sk_…`); the plaintext `secret` is shown ONLY once. * * Use the returned secret to build a fresh client and manage / charge on * the TPA(s) we have assigned to you: list them, mint per-TPA keys, * fill KYB requirements, upload documents. You do NOT create the TPA — that * happens when our team promotes your `applications.create()` submission. * * Served on the CRM plane (`/api/public/v1/processing/enroll`), since * the caller authenticates with a CRM key. * * @example * const crm = new Tagada({ apiKey: process.env.TAGADA_CRM_KEY }); * // 1. apply (lands in TagadaPay's review queue) * await crm.processing.applications.create({ businessInfo, representative }); * // 2. after our team assigns your TPA, mint a processing key and manage it * const { key } = await crm.processing.enroll({ mode: 'live' }); * const merchant = new Tagada({ apiKey: key.secret }); * const { data: tpas } = await merchant.processing.tpas.list(); */ enroll(params?: ProcessingEnrollParams, opts?: RequestOptions): Promise; } //# sourceMappingURL=Processing.d.ts.map