Skip to main content
These rules apply to every resource of the API. Each resource page only mentions the exceptions.

IDs in the path

Endpoints that receive an {id} in the path accept the public ID with its prefix or the value without the prefix: An ID that does not match any resource returns 404 RESOURCE_NOT_FOUND. For products, a prefix other than prd_ or a non-numeric value also returns 404.
Always store and use the prefixed ID the API returns: it is the one that appears in every response.

companyCode

If your client has a single company, you do not need to send companyCode: it is resolved from your token. If it has several companies, indicate which one you operate on with companyCode, as a query param (?companyCode=MX-S-04937) or in the body of a POST or PATCH:
  • If you do not send it, the API responds 400 BAD_REQUEST asking for it.
  • If you send a code that is not a company of your client, the API responds 422 RESOLUTION_ERROR.
  • In the PATCH endpoints (contacts, products, payment links, subscriptions, and debts), companyCode in the body is taken as context: it is not treated as a field to modify, nor rejected as a non-editable field.

Malformed JSON

A body that is not valid JSON returns 400 INVALID_REQUEST:
400 Malformed JSON

Pagination

List endpoints receive page and limit as query params and return the results in data together with a meta object: Invalid page or limit values do not return an error: they fall back to the default. meta.limit reflects the value that was applied.
Only GET /payment-links adds meta.capped: it is true when meta.total is approximate because the maximum number of items the service scans was reached. The other list endpoints do not carry that field.

Dates

  • date-time fields in responses (createdAt, updatedAt, expiresAt, etc.) always come in UTC with milliseconds and Z: 2026-09-24T17:38:21.107Z.
  • Date fields (dueDate, startDate, endDate) use YYYY-MM-DD and must be valid calendar dates (2026-02-30 returns 400).
  • The date-times you send (for example the expiresAt of a payment link) must be RFC 3339, with Z or an offset (2026-12-31T23:59:59-06:00). They are converted and stored in UTC, and returned in UTC even if you sent them with an offset.
  • The createdAtFrom and createdAtTo filters of list endpoints accept a date (YYYY-MM-DD) or an RFC 3339 date-time. A date alone covers the full UTC day, included at both ends. The details of each list are in Debts and Payment links.

Strict types

The API does not coerce types: each field must arrive with the type the contract declares.
  • Booleans: only accept the literal true or false. "true", 1, "yes", etc. return 400 INVALID_REQUEST with one entry in details[] per field. This applies to allowOverduePayment and allowPartialPayments in POST /v2/debts, to autopay, allowOverduePayment, allowPartialPayments, and enforcePaymentOrder in POST /subscriptions, and to the editable booleans of PATCH /subscriptions/{id}. The active query param of GET /products also accepts only true or false.
  • description: must be a string. Any other type returns 400.
  • Amounts: numbers in pesos with up to 2 decimals.
400 Non-literal boolean

additionalData

additionalData stores data from your own system alongside the charge. It is accepted in POST /v2/debts, POST /payment-links, and POST/PATCH /subscriptions, and it is persisted on the debt (for a payment link, on the debt associated with the link; for a subscription, on the debts it generates).
  • It must be a flat object. A scalar (string, number, or boolean) returns 400 INVALID_REQUEST.
  • It cannot use reserved keys, which TapiPay writes internally: description, paymentMethods, productName, externalProductId, debtExpirationDate, overduePayment, allowPartialPayments, recurringDebt, and debtReference. If any of them appears, the API responds 400 INVALID_REQUEST with details[].field = "additionalData".
Valid

Undeclared fields

  • In POST /v2/debts and in every PATCH, a field that is not in the contract returns 400 INVALID_REQUEST. In POST /v2/debts the field comes in details[].field.
  • In POST /contacts, POST /products, POST /payment-links, and POST /subscriptions, undeclared fields are ignored.

Validation errors

Validation errors return 400 INVALID_REQUEST with a details[] that indicates each field that failed and why. Use details[].field to show your user what to fix, and do not depend on the text of message or issue: they are informational and can change. In the batch mode of POST /v2/debts, each entry of details[] also carries index (the item’s position in debts) and externalRequestId. See Error handling.