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.
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_REQUESTasking for it. - If you send a code that is not a company of your client, the API responds
422 RESOLUTION_ERROR. - In the
PATCHendpoints (contacts, products, payment links, subscriptions, and debts),companyCodein 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 returns400 INVALID_REQUEST:
400 Malformed JSON
Pagination
List endpoints receivepage 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-timefields in responses (createdAt,updatedAt,expiresAt, etc.) always come in UTC with milliseconds andZ:2026-09-24T17:38:21.107Z.- Date fields (
dueDate,startDate,endDate) useYYYY-MM-DDand must be valid calendar dates (2026-02-30returns400). - The date-times you send (for example the
expiresAtof a payment link) must be RFC 3339, withZor 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
createdAtFromandcreatedAtTofilters 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
trueorfalse."true",1,"yes", etc. return400 INVALID_REQUESTwith one entry indetails[]per field. This applies toallowOverduePaymentandallowPartialPaymentsinPOST /v2/debts, toautopay,allowOverduePayment,allowPartialPayments, andenforcePaymentOrderinPOST /subscriptions, and to the editable booleans ofPATCH /subscriptions/{id}. Theactivequery param ofGET /productsalso accepts onlytrueorfalse. description: must be a string. Any other type returns400.- 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, anddebtReference. If any of them appears, the API responds400 INVALID_REQUESTwithdetails[].field = "additionalData".
Valid
Undeclared fields
- In
POST /v2/debtsand in everyPATCH, a field that is not in the contract returns400 INVALID_REQUEST. InPOST /v2/debtsthe field comes indetails[].field. - In
POST /contacts,POST /products,POST /payment-links, andPOST /subscriptions, undeclared fields are ignored.
Validation errors
Validation errors return400 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.
