También en markdown y en OpenAPI.
Referencia de la API de Makatea
Generada del OpenAPI de producción (versión
2026-09-27). URL base:https://makatea.ai/api. Las descripciones de rutas y campos vienen del spec, en inglés. Las guías en español están en https://makatea.ai/desarrolladores.
Introducción
The Makatea API lets your system create members and billing orders, register payments, and
receive events. Every response carries Makatea-Version (the version applied to the request; the old
name Makatea-API-Version carries the same value) and an X-Request-Id (send your own to correlate
logs). Current version: 2026-09-27.
Versions
A version is a date. Which one applies to a request:
- the
Makatea-Version: YYYY-MM-DDheader, if you send it (an unknown version is400 invalid_api_version); - otherwise, the version pinned to your API key (the current one on the day the key was created — keys created before 2026-09-27 stay on 2026-09-23, so nothing changes for existing integrations);
- otherwise (session JWT), the latest.
Webhook endpoints have their own frozen version (webhook_version, set when the endpoint is created): the shape of
an event never changes under you.
- 2026-09-23: First public version: API keys, Idempotency-Key, cursor pagination, webhooks with signed bodies.
- 2026-09-27: Request bodies: a field the operation does not declare is
422 unknown_field(it used to be ignored silently, like unknown query parameters before). Webhook events (endpoints on this version): the body carriesapi_versionandlivemode(falsefor events of a test organization).
Sync like an ERP
PUT /v1/members/by-ref/{external_ref}, PUT /v1/billing-orders/by-ref/{external_ref} and
PUT /v1/credits/by-ref/{external_ref} create or update by your identifier: 201 created, 200 updated,
200 unchanged when everything you sent is already so (nothing is written); the header
Makatea-Upsert-Result says which. POST /v1/members/batch, /v1/billing-orders/batch and
/v1/payments/batch take up to 500 rows, never fail as a whole (one result per row, with its index and error
code), support dry_run, and emit no webhooks and send no messages.
Authentication
Create an API key in Makatea → Settings → API. Send it in either header:
Authorization: Bearer mk_live_… (or mk_test_…)
X-API-Key: mk_live_…
Test keys (mk_test_…) work exactly the same against your organization's test copy («<org> · pruebas»,
created with the first test key): same rules and engine, separate data, and nothing leaves — messages are
recorded as simulated, there is no payment provider. Every response says Makatea-Livemode: true|false
and webhook events of the test copy carry "livemode": false (version 2026-09-27 or later).
Keys have scopes: read (GET) and write (everything else). A session JWT from the Makatea app
is also accepted in Authorization (legacy). Missing or invalid credentials → 401; a key
without the needed scope → 403 insufficient_scope.
Responses
Success always has the same shape, for single objects and for lists:
{"data": {…} }
{"data": [ … ], "pagination": {"limit": 100, "has_more": true, "next_cursor": "eyJm…"}}
Errors always look like this:
{"error": {"code": "validation_error", "message": "amount must be a positive number", "request_id": "…"}}
| Status | Meaning |
|---|---|
| 400 | Malformed request: invalid JSON, unknown query parameter (unknown_parameter lists the allowed ones), bad cursor |
| 401 | Missing/invalid credentials |
| 403 | Key lacks the scope |
| 404 | Not found (also unknown routes: route_not_found) |
| 405 | Route exists with another method |
| 409 | Conflict with the current state (already paid, duplicate external_ref, opted out, …) |
| 413 | Body or document too large |
| 422 | Validation error, or an Idempotency-Key reused with a different body |
| 429 | Rate limit exceeded (see Retry-After) |
| 5xx | Our fault; safe to retry with the same Idempotency-Key |
Pagination and sync
Lists accept limit (default 100, max 500) and cursor. Pass the next_cursor you received to
get the next page, keeping the same filters; stop when has_more is false. offset still
works for compatibility but can skip rows while data changes. Add count=true to get
pagination.total (slower).
To mirror data into your system, call the list with updated_since=<last sync instant>: results come
ordered by updated_at ascending, so you can page with the cursor and store the updated_at of the
last row as your next checkpoint.
Idempotency
Send Idempotency-Key: <unique string> on any POST/PUT/PATCH/DELETE. Retrying with the same key and
the same body returns the original response (with header Idempotent-Replayed: true) instead of
acting twice. The same key with a different body is 422 idempotency_key_reused; while the first
request is still running, 409 idempotency_in_progress. Keys are kept 24 hours.
Webhooks
Register an https endpoint (POST /v1/webhook-endpoints) with the event types you want (or *).
The response includes the signing secret (whsec_…) only once. Each event is POSTed as:
{"id": "<event id>", "type": "payment.received", "created_at": "…", "data": {…}}
(endpoints on version 2026-09-27 or later also get "api_version" and "livemode"), with headers
Makatea-Event-Id, Makatea-Event-Type, Makatea-Version (the endpoint's frozen version) and
Makatea-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256(secret, "<t>.<raw body>")>
Verify by recomputing the HMAC over t + "." + raw body and comparing in constant time; reject
timestamps older than 5 minutes. Answer 2xx within 10 seconds. Otherwise we retry after 1 min, 5 min,
30 min, 2 h, 6 h and 24 h; after 8 failed attempts the delivery is failed (you can retry it with
POST /v1/webhook-deliveries/{id}/retry). Deliveries can arrive more than once or out of order: use
the event id to de-duplicate.
Event types: member.created, member.updated, member.paused, member.resumed, billing_order.created, billing_order.updated, billing_order.paid, billing_order.cancelled, payment.received, payment.voided, payment_link.opened, promise.created, promise.kept, promise.broken, message.sent, message.received, message.classified. *.updated events carry
{"object": {…}, "previous_attributes": {…}}. Records created by CSV imports do not emit events.
Limits
600 requests per minute per API key (per organization for session JWTs), in fixed one-minute windows. Every response includes the IETF headers (draft-ietf-httpapi-ratelimit-headers)
RateLimit-Policy: "default";q=600;w=60
RateLimit: "default";r=598;t=37
(q quota per w-second window, r remaining, t seconds until the window resets) and the older
X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset (unix seconds). Over the limit → 429 with
Retry-After. A rejected request does not count: retrying while limited does not push the reset further.
Request bodies up to 21 MB; documents up to 15 MB; batches up to 500 rows.
Error codes
Every operation lists the codes it can return, grouped by HTTP status (x-error-codes has the same as a
map). The full catalog:
| Code | Status | Meaning |
|---|---|---|
already_delivered | 409 | The webhook delivery was already delivered. |
already_voided | 409 | The payment was already voided. |
amount_below_paid | 422 | The new amount is lower than what was already paid and forgiven. |
amount_exceeds_balance | 422 | The payment is larger than the balance and excess is reject. |
auth_unavailable | 503 | Could not verify the API key. Retry. |
batch_too_large | 413 | More rows than the batch limit (500). |
billing_orders_not_found | 422 | Some billing orders in the list do not exist (details.missing). |
breakdown_exceeds_amount | 422 | capital_portion + interest_portion is larger than amount. |
channel_unavailable | 503 | No connected line for that channel. |
comms_disabled | 409 | Messaging is turned off for this organization. |
conflict | 409 | A record with the same unique value (usually external_ref) already exists. |
credit_member_mismatch | 422 | The credit belongs to another member. |
credit_not_found | 422 | The credit referenced in the body (credit_id / credit_external_ref) does not exist. |
do_not_contact | 409 | The member is marked «do not contact»: nothing is sent to them. |
download_failed | 422 | The document URL could not be downloaded. |
duplicate_in_batch | 422 | Another row of the same batch has this external_ref; only the first is processed. |
external_ref_mismatch | 422 | external_ref in the body differs from the one in the path. |
external_ref_reused | 409 | A payment with this external_ref exists with a different order or amount. Void it and send a new one. |
flow_audience_not_editable | 409 | The flow's audience is defined by tags, segments or states, not by a member list. |
flow_not_active | 409 | The flow is not active. |
full_name_required | 422 | Creating a member needs full_name. |
idempotency_in_progress | 409 | A request with the same Idempotency-Key is still running. Retry shortly. |
idempotency_key_reused | 422 | The Idempotency-Key was already used with a different request body. |
idempotency_unavailable | 503 | Could not record the Idempotency-Key. Retry. |
immutable_field | 422 | The field can only be set when the record is created. |
import_failed | 502 | The conversation import service failed. |
insufficient_scope | 403 | The API key lacks the scope this operation needs (read for GET, write for the rest). |
internal_error | 500 | Our fault. Safe to retry with the same Idempotency-Key. |
invalid_api_key | 401 | The API key (mk_live_… or mk_test_…) does not exist, was revoked or expired. |
invalid_api_version | 400 | The Makatea-Version header names a version that does not exist. details.versions lists the valid ones. |
invalid_cursor | 400 | The cursor is malformed or belongs to another ordering. Keep the same filters between pages. |
invalid_idempotency_key | 400 | Idempotency-Key must be 1 to 255 characters. |
invalid_json | 400 | The body is not valid JSON, is not an object, or is missing when required. |
invalid_parameter | 400 | A query parameter has an invalid value (not a UUID, not a date, out of range). |
invalid_reference | 422 | A referenced record does not exist. |
member_mismatch | 409 | The external_ref belongs to a record of another member. Moving is explicit (PATCH with member_id). |
member_not_found | 422 | The member referenced in the body (member_id / member_external_ref) does not exist. |
method_not_allowed | 405 | The route exists with another method (see the Allow header). |
no_active_promise | 409 | The member has no active payment promise. |
no_org | 403 | Session JWT of a user that has not finished onboarding. |
no_payment_provider | 409 | The organization has no active payment provider. |
no_recipient | 422 | The member has no phone (WhatsApp/SMS) or no email (email). |
not_found | 404 | The resource does not exist in your organization. |
not_paused | 409 | The member is not paused. |
not_voidable | 409 | Reversal entries cannot be voided. |
nothing_to_forgive | 409 | The billing order has no balance to forgive. |
opted_out | 409 | The member opted out of messages. |
order_cancelled | 409 | The billing order is cancelled. |
order_has_payments | 409 | The billing order has payments or forgiveness; only an untouched balance can be transferred. |
order_not_found | 422 | The billing order referenced in the body does not exist. |
order_not_open | 409 | The operation needs a pending or overdue billing order. |
order_paid | 409 | The billing order is already paid. |
outside_send_window | 409 | Outside the organization's send window. |
payload_too_large | 413 | Body over 21 MB or document over 15 MB. |
payment_link_unavailable | 502 | The payment provider could not create the link. |
payment_voided | 409 | The Idempotency-Key belongs to a payment that was voided. A voided payment is not re-applied: send the new payment with a new key. details.payment_id is the voided one. |
plan_limit_reached | 402 | Your plan's member limit is reached. |
rate_limited | 429 | Over the per-minute limit. Wait Retry-After seconds. Rejected requests do not count against the limit. |
reason_required | 422 | do_not_contact: true needs do_not_contact_reason. |
route_not_found | 404 | No such route. |
schedule_on_existing_credit | 409 | schedule only applies when the credit is created; it already has installments. |
send_failed | 502 | The channel provider rejected the message. |
split_breakdown_partially_paid | 409 | A billing order with a capital/interest breakdown and payments cannot be split; void the payments or remove the breakdown first. |
split_sum_mismatch | 422 | The parts of a split do not add up to the balance to the cent (details.expected, details.got). |
storage_error | 502 | The document could not be stored. |
template_inactive | 409 | The template is not active. |
transfer_not_allowed | 409 | The destination order is cancelled, paid (with add_to_destination), the same order, or belongs to another member. |
unauthorized | 401 | Missing or invalid credentials. |
unknown_field | 422 | A body field the operation does not accept (API version 2026-09-27 or later). details.field names it. |
unknown_parameter | 400 | A query parameter the route does not declare. details.allowed lists the valid ones. |
validation_error | 422 | A field is missing or has an invalid value. details.field names it. |
Status
GET /v1/status (no key) says whether the service and its database answer.
Índice de rutas
- Status
- Members
- Sync
- Promises
- Collection control
- Credit
- Messages
- Documents
- Billing orders
GET /v1/billing-ordersPOST /v1/billing-ordersGET /v1/billing-orders/{id}PATCH /v1/billing-orders/{id}DELETE /v1/billing-orders/{id}POST /v1/billing-orders/{id}/transferPOST /v1/billing-orders/{id}/splitPOST /v1/billing-orders/{id}/forgivePOST /v1/billing-orders/{id}/late-feesPOST /v1/billing-orders/{id}/payment-link
- Payments
- Credits (loans)
- Settings
- Webhooks
- Operations
Status
GET /v1/status
Service status (no authentication).
Checks that the database answers. Returns 503 when it does not.
Respuestas
200OK ·data: Status
Members
GET /v1/members
List members.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
state | query | string: contact, active, at_risk, delinquent, dormant, churned | ||
q | query | string | Search in name or phone. | |
external_ref | query | string | Exact match on your own identifier. | |
updated_since | query | string (date-time) | Only records changed at or after this instant (ISO-8601). Switches ordering to updated_at ascending, so you can resume a sync with the last next_cursor. | |
include_erased | query | boolean | Include members erased for privacy (full_name «[titular eliminado]», no phone). They are not customers anymore: left out by default, like in the app. | |
limit | query | integer | ||
cursor | query | string | next_cursor from the previous page. | |
offset | query | integer | Legacy; prefer cursor. | |
count | query | boolean | Include pagination.total. | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: array de Member400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_cursor — The cursor is malformed or belongs to another ordering. Keep the same filters between pages.
invalid_parameter — A query parameter has an invalid value (not a UUID, not a date, out of range).
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/members
Create a member.
Two members may share a phone number. external_ref is unique per organization (409 if reused).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
full_name | string | sí | |
first_name | string, nullable | The name used to greet the member ({{member_first_name}}). Without it, the first word of full_name. | |
phone_e164 | string | Normalized to E.164 (10 bare digits are read as Mexico; +521… becomes +52…). 422 if it is not a recognizable phone. Ejemplo: "+525512345678". | |
email | string | ||
state | string: contact, active, at_risk, delinquent, dormant, churned | Por omisión: "contact". | |
external_ref | string | Your identifier for this member. | |
identity | object | Free-form attributes (used as template variables). | |
tags | array de string | ||
notes | string | ||
customer_since | string (date) | When the member became your customer (not when it entered Makatea). Not in the future. | |
do_not_contact | boolean | Never send this member any message. Requires do_not_contact_reason. Por omisión: false. | |
do_not_contact_reason | string |
Respuestas
201OK ·data: Member400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
402plan_limit_reached— Your plan's member limit is reached.403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).409conflict— A record with the same unique value (usuallyexternal_ref) already exists.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
reason_required — do_not_contact: true needs do_not_contact_reason.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
GET /v1/members/{id}
Get a member (with billing orders and recent interactions).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: Member400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
PUT /v1/members/{id}
Update a member.
Only the fields you send are changed.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
full_name | string | ||
first_name | string, nullable | The name used to greet the member ({{member_first_name}}). Without it, the first word of full_name. | |
phone_e164 | string, nullable | Normalized to E.164; 422 if not a recognizable phone. | |
email | string, nullable | ||
state | string: contact, active, at_risk, delinquent, dormant, churned | ||
external_ref | string, nullable | ||
identity | object | ||
tags | array de string | ||
notes | string, nullable | ||
customer_since | string (date), nullable | Not in the future. null clears it. | |
do_not_contact | boolean | true requires do_not_contact_reason (sent now or already on file); false clears the reason. Pending messages are withdrawn when it turns on. | |
do_not_contact_reason | string | Can be sent alone to change the reason of a member already marked. |
Respuestas
200OK ·data: Member400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409conflict— A record with the same unique value (usuallyexternal_ref) already exists.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
reason_required — do_not_contact: true needs do_not_contact_reason.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
PATCH /v1/members/{id}
Update a member (partial).
Only the fields you send are changed.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
full_name | string | ||
first_name | string, nullable | The name used to greet the member ({{member_first_name}}). Without it, the first word of full_name. | |
phone_e164 | string, nullable | Normalized to E.164; 422 if not a recognizable phone. | |
email | string, nullable | ||
state | string: contact, active, at_risk, delinquent, dormant, churned | ||
external_ref | string, nullable | ||
identity | object | ||
tags | array de string | ||
notes | string, nullable | ||
customer_since | string (date), nullable | Not in the future. null clears it. | |
do_not_contact | boolean | true requires do_not_contact_reason (sent now or already on file); false clears the reason. Pending messages are withdrawn when it turns on. | |
do_not_contact_reason | string | Can be sent alone to change the reason of a member already marked. |
Respuestas
200OK ·data: Member400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409conflict— A record with the same unique value (usuallyexternal_ref) already exists.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
reason_required — do_not_contact: true needs do_not_contact_reason.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
DELETE /v1/members/{id}
Soft-delete a member (state becomes churned).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Respuestas
200OK ·data: Member400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409idempotency_in_progress— A request with the same Idempotency-Key is still running. Retry shortly.422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
Sync
PUT /v1/members/by-ref/{external_ref}
Create or update a member by your external_ref (upsert).
The member identified by external_ref (your id) ends up as the body says. Does not exist → created, 201. Exists and something changed → only the fields you sent are updated, 200. Exists and every field you sent is equal → nothing is written (not even updated_at), 200. The header Makatea-Upsert-Result says which (created, updated, unchanged). Fields you omit are not touched; null clears a nullable field. Emits member.created / member.updated like the other routes (a batch does not).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
external_ref | path | string | sí | Your identifier (URL-encode it). |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
external_ref | string | Your identifier: the upsert key (unique per organization). | |
full_name | string | Required to create. | |
first_name | string, nullable | The name used to greet the member ({{member_first_name}}). Without it, the first word of full_name. | |
phone_e164 | string, nullable | ||
email | string, nullable | ||
state | string: contact, active, at_risk, delinquent, dormant, churned | Derived from the member's orders: contact (no orders), active (nothing overdue), delinquent (1 to 60 days late), dormant (more than 60). A new member starts as contact. | |
identity | object | Replaces the whole object. | |
tags | array de string | Replaces the whole list. | |
notes | string, nullable | ||
customer_since | string (date), nullable | ||
do_not_contact | boolean | ||
do_not_contact_reason | string, nullable |
Respuestas
200OK ·data: Member400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
402plan_limit_reached— Your plan's member limit is reached.403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409conflict— A record with the same unique value (usuallyexternal_ref) already exists.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
422external_ref_mismatch—external_refin the body differs from the one in the path.
full_name_required — Creating a member needs full_name.
idempotency_key_reused — The Idempotency-Key was already used with a different request body.
reason_required — do_not_contact: true needs do_not_contact_reason.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/members/batch
Create or update up to 500 members by external_ref.
Never fails as a whole: each row gets its own result (created, updated, unchanged or failed with error.code, error.message, error.field), in the same order and with its index (0-based). Rows are matched by external_ref; sending the same batch twice leaves the data exactly as it was (the second time every row is unchanged). A repeated external_ref inside one batch: the first row wins, the others fail with duplicate_in_batch. dry_run: true runs everything (locks, constraints, triggers) and rolls it back: the results are the ones you would get for real. Batches emit no webhooks and send no messages (the records carry import_batch_id = batch_id); single-row calls (PUT …/by-ref/…) do emit. Each row has the same fields as PUT /v1/members/by-ref/{external_ref} plus external_ref.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
dry_run | boolean | Por omisión: false. | |
rows | array de object | sí |
Cada elemento de rows:
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
external_ref | string | sí | Your identifier: the upsert key (unique per organization). |
full_name | string | Required to create. | |
first_name | string, nullable | The name used to greet the member ({{member_first_name}}). Without it, the first word of full_name. | |
phone_e164 | string, nullable | ||
email | string, nullable | ||
state | string: contact, active, at_risk, delinquent, dormant, churned | Derived from the member's orders: contact (no orders), active (nothing overdue), delinquent (1 to 60 days late), dormant (more than 60). A new member starts as contact. | |
identity | object | Replaces the whole object. | |
tags | array de string | Replaces the whole list. | |
notes | string, nullable | ||
customer_since | string (date), nullable | ||
do_not_contact | boolean | ||
do_not_contact_reason | string, nullable |
Respuestas
200OK ·data: BatchResult400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
402plan_limit_reached— Your plan's member limit is reached.403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).409conflict— A record with the same unique value (usuallyexternal_ref) already exists.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
413batch_too_large— More rows than the batch limit (500).422duplicate_in_batch— Another row of the same batch has thisexternal_ref; only the first is processed.
full_name_required — Creating a member needs full_name.
idempotency_key_reused — The Idempotency-Key was already used with a different request body.
reason_required — do_not_contact: true needs do_not_contact_reason.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
PUT /v1/billing-orders/by-ref/{external_ref}
Create or update a billing order by your external_ref (upsert).
Same contract as PUT /v1/members/by-ref/{external_ref}: 201 created, 200 updated or unchanged, header Makatea-Upsert-Result. To create, send member_id (or member_external_ref), amount and due_date. Updates go through the same path as PATCH /v1/billing-orders/{id} (moving due_date re-schedules its reminders, changing the breakdown re-applies its payments). An external_ref that belongs to another member's order is 409 member_mismatch (moving is explicit, with PATCH); cancelled orders are 409 order_cancelled.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
external_ref | path | string | sí | Your identifier (URL-encode it). |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
external_ref | string | Your identifier: the upsert key (unique per organization). | |
member_id | string (uuid) | ||
member_external_ref | string | Instead of member_id. | |
amount | number | Required to create. | |
due_date | string (date) | Required to create. | |
currency | string | Only when created (immutable_field afterwards). Por omisión: "MXN". | |
period_label | string, nullable | ||
notes | string, nullable | ||
capital_portion | number, nullable | ||
interest_portion | number, nullable | ||
credit_id | string (uuid), nullable | ||
credit_external_ref | string, nullable | Instead of credit_id. |
Respuestas
200OK ·data: BillingOrder400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409conflict— A record with the same unique value (usuallyexternal_ref) already exists.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
member_mismatch — The external_ref belongs to a record of another member. Moving is explicit (PATCH with member_id).
order_cancelled — The billing order is cancelled.
422amount_below_paid— The new amount is lower than what was already paid and forgiven.
breakdown_exceeds_amount — capital_portion + interest_portion is larger than amount.
credit_member_mismatch — The credit belongs to another member.
credit_not_found — The credit referenced in the body (credit_id / credit_external_ref) does not exist.
external_ref_mismatch — external_ref in the body differs from the one in the path.
idempotency_key_reused — The Idempotency-Key was already used with a different request body.
immutable_field — The field can only be set when the record is created.
member_not_found — The member referenced in the body (member_id / member_external_ref) does not exist.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/billing-orders/batch
Create or update up to 500 billing orders by external_ref.
Never fails as a whole: each row gets its own result (created, updated, unchanged or failed with error.code, error.message, error.field), in the same order and with its index (0-based). Rows are matched by external_ref; sending the same batch twice leaves the data exactly as it was (the second time every row is unchanged). A repeated external_ref inside one batch: the first row wins, the others fail with duplicate_in_batch. dry_run: true runs everything (locks, constraints, triggers) and rolls it back: the results are the ones you would get for real. Batches emit no webhooks and send no messages (the records carry import_batch_id = batch_id); single-row calls (PUT …/by-ref/…) do emit. Each row has the same fields as PUT /v1/billing-orders/by-ref/{external_ref} plus external_ref. New orders are scheduled for collection like any other (the reminders are the calendar, not a notification).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
dry_run | boolean | Por omisión: false. | |
rows | array de object | sí |
Cada elemento de rows:
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
external_ref | string | sí | Your identifier: the upsert key (unique per organization). |
member_id | string (uuid) | ||
member_external_ref | string | Instead of member_id. | |
amount | number | Required to create. | |
due_date | string (date) | Required to create. | |
currency | string | Only when created (immutable_field afterwards). Por omisión: "MXN". | |
period_label | string, nullable | ||
notes | string, nullable | ||
capital_portion | number, nullable | ||
interest_portion | number, nullable | ||
credit_id | string (uuid), nullable | ||
credit_external_ref | string, nullable | Instead of credit_id. |
Respuestas
200OK ·data: BatchResult400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).409conflict— A record with the same unique value (usuallyexternal_ref) already exists.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
member_mismatch — The external_ref belongs to a record of another member. Moving is explicit (PATCH with member_id).
order_cancelled — The billing order is cancelled.
413batch_too_large— More rows than the batch limit (500).422amount_below_paid— The new amount is lower than what was already paid and forgiven.
breakdown_exceeds_amount — capital_portion + interest_portion is larger than amount.
credit_member_mismatch — The credit belongs to another member.
credit_not_found — The credit referenced in the body (credit_id / credit_external_ref) does not exist.
duplicate_in_batch — Another row of the same batch has this external_ref; only the first is processed.
idempotency_key_reused — The Idempotency-Key was already used with a different request body.
immutable_field — The field can only be set when the record is created.
member_not_found — The member referenced in the body (member_id / member_external_ref) does not exist.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
PUT /v1/credits/by-ref/{external_ref}
Create or update a credit (loan) by its folio (upsert).
Same contract as the other by-ref routes: 201 created, 200 updated or unchanged, header Makatea-Upsert-Result. To create, send member_id (or member_external_ref), principal and start_date. A folio of another member is 409 member_mismatch. status accepts active or cancelled.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
external_ref | path | string | sí | Your identifier (URL-encode it). |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
member_id | string (uuid) | ||
member_external_ref | string | ||
principal | number | ||
start_date | string (date) | ||
total_amount | number, nullable | ||
periods | integer, nullable | ||
frequency | string: weekly, biweekly, semimonthly, monthly, daily, other, nullable | ||
notes | string, nullable | ||
status | string: active, cancelled | ||
schedule | object | Only when the PUT creates the credit (see POST /v1/credits). On an existing credit the same schedule is unchanged and a different one is 409 schedule_on_existing_credit. |
Respuestas
200OK ·data: LoanDetail400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409conflict— A record with the same unique value (usuallyexternal_ref) already exists.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
member_mismatch — The external_ref belongs to a record of another member. Moving is explicit (PATCH with member_id).
schedule_on_existing_credit — schedule only applies when the credit is created; it already has installments.
422external_ref_mismatch—external_refin the body differs from the one in the path.
idempotency_key_reused — The Idempotency-Key was already used with a different request body.
member_not_found — The member referenced in the body (member_id / member_external_ref) does not exist.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/payments/batch
Register up to 500 payments (reconciliation).
Each row is one payment to one billing order (billing_order_id or billing_order_external_ref). The row's external_ref is your payment folio and makes the batch idempotent: a folio already registered with the same order and amount is unchanged (with its id), with a different order or amount it fails with external_ref_reused (void it and send a new folio). excess works like in POST /v1/billing-orders/{id}/payments. The ledger is append-only: payments are never updated. Rows run in order, so two payments to the same order see each other's effect. By default members are not notified (no «we received your payment» message) and no webhooks are emitted; send notify_members: true to send the organization's payment confirmations as if each payment came one by one. Never fails as a whole; dry_run rolls everything back.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
dry_run | boolean | Por omisión: false. | |
notify_members | boolean | Por omisión: false. | |
rows | array de object | sí |
Cada elemento de rows:
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
external_ref | string | sí | Your payment folio: the idempotency key. Same folio + same order and amount = unchanged; different = external_ref_reused. |
billing_order_id | string (uuid) | ||
billing_order_external_ref | string | Instead of billing_order_id. | |
amount | number | sí | |
paid_at | string | When the money was received (date or ISO-8601; a date without time is that day in the organization's timezone). Default: now. Not in the future. | |
method | string | ||
reference | string | ||
notes | string | ||
excess | string: reject, credit | Por omisión: "reject". |
Respuestas
200OK ·data: BatchResult400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).409external_ref_reused— A payment with thisexternal_refexists with a different order or amount. Void it and send a new one.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
order_cancelled — The billing order is cancelled.
order_paid — The billing order is already paid.
413batch_too_large— More rows than the batch limit (500).422amount_exceeds_balance— The payment is larger than the balance andexcessisreject.
duplicate_in_batch — Another row of the same batch has this external_ref; only the first is processed.
idempotency_key_reused — The Idempotency-Key was already used with a different request body.
order_not_found — The billing order referenced in the body does not exist.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
Promises
GET /v1/members/{id}/promises
Current promise and history.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: PromiseState400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/members/{id}/promises
Record a payment promise.
Pauses collection messages until the promised date (one reminder survives). Replaces any active promise. When the date passes the promise becomes kept or broken (webhooks promise.kept / promise.broken).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
promised_date | string (date) | sí | |
amount | number |
Respuestas
201OK ·data: PromiseState400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409idempotency_in_progress— A request with the same Idempotency-Key is still running. Retry shortly.422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
DELETE /v1/members/{id}/promises/current
Cancel the active promise.
Marks it cancelled (kept in history) and re-schedules collection for the member's open orders. 409 if there is no active promise.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Respuestas
200OK ·data: PromiseState400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409idempotency_in_progress— A request with the same Idempotency-Key is still running. Retry shortly.
no_active_promise — The member has no active payment promise.
422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
Collection control
POST /v1/members/{id}/pause
Pause collection for a member until a date.
Stops automatic collection and campaign messages to this member until until, through the same mechanism a payment promise uses: of the reminders due before until, only the one for the most serious delay survives (moved to until); the rest are withdrawn, and nothing new is scheduled before until. Event notices (payment confirmations) and explicit sends (POST /v1/messages) still go out. until as a date (2026-10-10) means 08:00 in the organization's timezone that day; a date-time without offset is local time. Pausing an already paused member replaces the date. When until passes, collection simply resumes (no call needed). Emits member.paused.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
until | string | sí | Date (YYYY-MM-DD) or ISO-8601 timestamp. Future, at most 1 year ahead. Ejemplo: "2026-10-10". |
reason | string | Why (shown in the app and in the event). |
Respuestas
200OK ·data: PauseState400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409idempotency_in_progress— A request with the same Idempotency-Key is still running. Retry shortly.422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/members/{id}/resume
Resume collection now (end a pause early).
Ends the pause. The reminder that was waiting for the end of the pause is moved to the member's next decent hour (08:00–22:00 local, otherwise the next morning), and the reminders the pause withdrew that are still in the future are scheduled again. 409 not_paused if there is no active pause. Emits member.resumed.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Respuestas
200OK ·data: PauseState400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409idempotency_in_progress— A request with the same Idempotency-Key is still running. Retry shortly.
not_paused — The member is not paused.
422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/flows/{id}/members
Enroll a member in a flow (flows whose audience is a member list).
Adds the member to the flow's explicit audience list and, if the flow is active, schedules its messages right away (idempotent: enrolling twice changes nothing). Only flows with audience_mode: members have a list; a flow whose audience is defined by tags, segments or states answers 409 flow_audience_not_editable (membership there follows that criterion: change the member's tags or state instead).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
member_id | string (uuid) | sí |
Respuestas
200OK ·data: FlowMembership400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409flow_audience_not_editable— The flow's audience is defined by tags, segments or states, not by a member list.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
DELETE /v1/flows/{id}/members/{member_id}
Remove a member from a flow (member-list flows).
Removes the member from the flow's list and withdraws its pending messages of that flow. Same 409 flow_audience_not_editable rule as enrolling.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
member_id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Respuestas
200OK ·data: FlowMembership400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409flow_audience_not_editable— The flow's audience is defined by tags, segments or states, not by a member list.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
Credit
GET /v1/members/{id}/credit
Credit balance and its ledger.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: Credit400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/members/{id}/credit/apply
Apply the credit balance to open orders (oldest first).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Respuestas
200OK ·data: CreditApplied400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409idempotency_in_progress— A request with the same Idempotency-Key is still running. Retry shortly.422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
Messages
GET /v1/members/{id}/conversation
Messages exchanged with a member (newest first).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
channel | query | string: whatsapp, sms, email | ||
limit | query | integer | ||
cursor | query | string | next_cursor from the previous page. | |
offset | query | integer | Legacy; prefer cursor. | |
count | query | boolean | Include pagination.total. | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: array de Interaction400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_cursor — The cursor is malformed or belongs to another ordering. Keep the same filters between pages.
invalid_parameter — A query parameter has an invalid value (not a UUID, not a date, out of range).
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/messages
Send a message to a member.
With text: sent right away through the organization's line (WhatsApp or SMS) — status: sent.
With template_id: queued for the sending engine, which renders the template variables — status: queued (any channel, including email).
Respects opt-outs (409 opted_out), the organization's kill switch (409 comms_disabled) and its send window (409 outside_send_window, text only; queued messages wait for the window).
Organizations in simulation mode record the message but nothing leaves (status: simulated).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
member_id | string (uuid) | sí | |
channel | string: whatsapp, sms, email | Por omisión: "whatsapp". | |
text | string | ||
template_id | string (uuid) |
Respuestas
202OK ·data: MessageResult400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409comms_disabled— Messaging is turned off for this organization.
do_not_contact — The member is marked «do not contact»: nothing is sent to them.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
opted_out — The member opted out of messages.
outside_send_window — Outside the organization's send window.
template_inactive — The template is not active.
422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
no_recipient — The member has no phone (WhatsApp/SMS) or no email (email).
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.502send_failed— The channel provider rejected the message.503channel_unavailable— No connected line for that channel.
POST /v1/conversations/import
Import conversation history (messages that happened outside Makatea).
Up to 20,000 rows per call. Idempotent by external_id (or by member + time + direction + text). Imported messages trigger nothing: no auto-replies, no notices, no webhooks. dry_run validates without writing. Members are matched by member_external_ref, or by phone when exactly one member has it. Re-sending a row that was imported without its attachment completes it.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
dry_run | boolean | ||
rows | array de object |
Cada elemento de rows:
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
member_external_ref | string | ||
phone | string | ||
occurred_at | string (date-time) | sí | |
direction | string: inbound, outbound | sí | |
channel | string: whatsapp, email, sms | sí | |
body | string | sí | |
subject | string | ||
external_id | string | ||
media_url | string | https link to the attachment (photo, voice note, sticker, video, document). Makatea downloads and stores it (max 20 MB). Requires external_id; body may then be empty. | |
media_mime | string | ||
media_name | string | ||
reactions | array de object |
Respuestas
200OK ·data: ConversationImportResult400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).409idempotency_in_progress— A request with the same Idempotency-Key is still running. Retry shortly.413payload_too_large— Body over 21 MB or document over 15 MB.422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.502import_failed— The conversation import service failed.
Documents
GET /v1/members/{id}/documents
List a member's documents (with temporary download URLs, valid 1 hour).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
external_ref | query | string | Exact match on your own identifier. | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: array de Document400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_parameter — A query parameter has an invalid value (not a UUID, not a date, out of range).
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/members/{id}/documents
Attach a document to a member.
Send the file inline (content_base64) or a public https url the server downloads. Max 15 MB. With external_ref, repeating the call returns the existing document (200) instead of uploading twice.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
name | string | sí | |
mime_type | string | ||
content_base64 | string (byte) | ||
url | string (uri) | ||
external_ref | string | ||
type | string: ine_frontal, ine_reverso, comprobante, otro | Por omisión: "otro". | |
description | string |
Respuestas
201OK ·data: Document400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409idempotency_in_progress— A request with the same Idempotency-Key is still running. Retry shortly.413payload_too_large— Body over 21 MB or document over 15 MB.422download_failed— The document URL could not be downloaded.
idempotency_key_reused — The Idempotency-Key was already used with a different request body.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.502storage_error— The document could not be stored.
DELETE /v1/members/{id}/documents/{document_id}
Delete a document (file and record).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
document_id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Respuestas
200OK ·data: Deleted400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409idempotency_in_progress— A request with the same Idempotency-Key is still running. Retry shortly.422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
Billing orders
GET /v1/billing-orders
List billing orders.
Default order: due_date ascending. With updated_since: updated_at ascending.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
status | query | string: pending, overdue, paid, cancelled | ||
member_id | query | string (uuid) | ||
external_ref | query | string | Exact match on your own identifier. | |
updated_since | query | string (date-time) | Only records changed at or after this instant (ISO-8601). Switches ordering to updated_at ascending, so you can resume a sync with the last next_cursor. | |
credit_id | query | string (uuid) | Only the installments of this credit. | |
due_from | query | string (date) | ||
due_to | query | string (date) | ||
limit | query | integer | ||
cursor | query | string | next_cursor from the previous page. | |
offset | query | integer | Legacy; prefer cursor. | |
count | query | boolean | Include pagination.total. | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: array de BillingOrder400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_cursor — The cursor is malformed or belongs to another ordering. Keep the same filters between pages.
invalid_parameter — A query parameter has an invalid value (not a UUID, not a date, out of range).
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/billing-orders
Create a billing order.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
member_id | string (uuid) | sí | |
amount | number | sí | |
currency | string | Por omisión: "MXN". | |
due_date | string (date) | sí | |
period_label | string | ||
external_ref | string | Unique per organization. | |
notes | string | ||
capital_portion | number, nullable | Principal part of this installment. Send together with interest_portion (both null removes the breakdown). capital + interest ≤ amount; the rest of amount is the collectible late fee and, beyond it, «other charges». | |
interest_portion | number, nullable | Interest part of this installment (include commissions you consider interest). | |
credit_id | string (uuid), nullable | Credit (loan) this installment belongs to; must be of the same member. null detaches it. |
Respuestas
201OK ·data: BillingOrder400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409conflict— A record with the same unique value (usuallyexternal_ref) already exists.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
422breakdown_exceeds_amount—capital_portion + interest_portionis larger thanamount.
credit_member_mismatch — The credit belongs to another member.
idempotency_key_reused — The Idempotency-Key was already used with a different request body.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
GET /v1/billing-orders/{id}
Get a billing order.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: BillingOrder400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
PATCH /v1/billing-orders/{id}
Update a billing order (move the date, change the amount, …).
Moving due_date re-schedules its collection messages. Raising amount above what was paid re-opens a paid order; lowering it to what is covered marks it paid. late_fee sets the accumulated late fee (absolute). capital_portion/interest_portion set the breakdown (also on paid orders: it is history) and re-apply the order's payments. Cancelled orders cannot be edited (409).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
due_date | string (date) | ||
amount | number | ||
period_label | string, nullable | ||
late_fee | number | ||
external_ref | string, nullable | ||
notes | string, nullable | ||
member_id | string (uuid) | Move the order (with its payments) to another member of the organization. | |
capital_portion | number, nullable | Principal part of this installment. Send together with interest_portion (both null removes the breakdown). capital + interest ≤ amount; the rest of amount is the collectible late fee and, beyond it, «other charges». | |
interest_portion | number, nullable | Interest part of this installment (include commissions you consider interest). | |
credit_id | string (uuid), nullable | Credit (loan) this installment belongs to; must be of the same member. null detaches it. |
Respuestas
200OK ·data: BillingOrder400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409conflict— A record with the same unique value (usuallyexternal_ref) already exists.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
order_cancelled — The billing order is cancelled.
422amount_below_paid— The new amount is lower than what was already paid and forgiven.
breakdown_exceeds_amount — capital_portion + interest_portion is larger than amount.
credit_member_mismatch — The credit belongs to another member.
idempotency_key_reused — The Idempotency-Key was already used with a different request body.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
DELETE /v1/billing-orders/{id}
Cancel a billing order (409 if already paid).
Optional reason (query ?reason= or JSON body {"reason": …}, max 500 chars) is stored as cancel_reason — e.g. «consolidated into another account». Cancelling an already cancelled order with a reason updates the reason.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
reason | query | string | Why the order is cancelled (stored as cancel_reason). | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
reason | string |
Respuestas
200OK ·data: BillingOrder400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
invalid_parameter — A query parameter has an invalid value (not a UUID, not a date, out of range).
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409idempotency_in_progress— A request with the same Idempotency-Key is still running. Retry shortly.
order_paid — The billing order is already paid.
422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/billing-orders/{id}/transfer
Transfer an installment's balance to another installment of the same member.
For a debt that is now collected elsewhere (restructure, consolidation into a new loan). The origin must be open and untouched (no payments, no forgiveness); it becomes cancelled with transferred_to_order_id and cancel_reason (reason or «Traspasada a <destination>»), and its collection stops. Its credit is liquidated by itself when nothing else of it is open. The destination's amount does not change unless add_to_destination is true (when your system did not already include it). Repeating the same transfer answers 200 with already_transferred. Do not send an amount of 0 to say this: amounts must be positive.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
to_order_id | string (uuid) | ||
to_order_external_ref | string | Your folio of the destination installment (same member). | |
reason | string | ||
add_to_destination | boolean | Por omisión: false. |
Respuestas
200OK ·data: TransferResult400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409idempotency_in_progress— A request with the same Idempotency-Key is still running. Retry shortly.
order_has_payments — The billing order has payments or forgiveness; only an untouched balance can be transferred.
order_not_open — The operation needs a pending or overdue billing order.
transfer_not_allowed — The destination order is cancelled, paid (with add_to_destination), the same order, or belongs to another member.
422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
order_not_found — The billing order referenced in the body does not exist.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/billing-orders/{id}/split
Split a billing order into several (explicit parts or generated installments).
Splits what is still owed (amount − amount_paid − amount_forgiven) into new billing orders of the same member, credit and currency, each with parent_order_id = this one. Either send parts (2 to 60 {amount, due_date, period_label?, external_ref?} that must add up exactly to the balance, else 422 split_sum_mismatch with details.expected), or installments (2 to 60) + frequency (default monthly) + first_due_date (default: the order's due date, or today in the organization's timezone if that already passed): the balance is split to the cent and the last one absorbs the rounding. The original is kept as history: with nothing paid it becomes cancelled (cancel_reason = reason or «Dividida en N partes»); with partial payments its amount is lowered to what was covered and it becomes paid. A breakdown (capital/interest) is split proportionally; an order with a breakdown and payments cannot be split (409 split_breakdown_partially_paid). Only pending/overdue orders (409 order_not_open).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
parts | array de object | ||
installments | integer | ||
frequency | string: weekly, biweekly, semimonthly, monthly | Por omisión: "monthly". | |
first_due_date | string (date) | ||
reason | string |
Cada elemento de parts:
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
amount | number | sí | |
due_date | string (date) | sí | |
period_label | string | ||
external_ref | string |
Respuestas
201OK ·data: SplitResult400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409conflict— A record with the same unique value (usuallyexternal_ref) already exists.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
order_not_open — The operation needs a pending or overdue billing order.
split_breakdown_partially_paid — A billing order with a capital/interest breakdown and payments cannot be split; void the payments or remove the breakdown first.
422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
split_sum_mismatch — The parts of a split do not add up to the balance to the cent (details.expected, details.got).
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/billing-orders/{id}/forgive
Forgive (condone) part or all of the balance.
Forgiven money is not a payment: it does not appear in /v1/payments. Without amount, forgives the whole balance and the order becomes paid. On orders with a breakdown the forgiveness takes, of what is still owed, late fee first, then interest, then other charges and principal last (forgiven_now_breakdown; forgiven principal is a loss).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
amount | number | ||
reason | string |
Respuestas
200OK ·data: BillingOrder400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409idempotency_in_progress— A request with the same Idempotency-Key is still running. Retry shortly.
nothing_to_forgive — The billing order has no balance to forgive.
order_cancelled — The billing order is cancelled.
422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/billing-orders/{id}/late-fees
Add a late fee to an order.
Adds to late_fee and fires the late_fee_applied notice if the organization configured one. With collectible: true the fee is also added to amount (it becomes owed; a paid order re-opens). When omitted, the organization's moratorio_cobrable setting decides (default: informational only).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
amount | number | sí | |
collectible | boolean |
Respuestas
201OK ·data: BillingOrder400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409idempotency_in_progress— A request with the same Idempotency-Key is still running. Retry shortly.
order_cancelled — The billing order is cancelled.
422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/billing-orders/{id}/payment-link
Create (or reuse) a payment link, optionally send it to the member.
Creates the link with the organization's payment provider, or returns the current one if it has not expired (url: Stripe Checkout, or Makatea's page for OXXO/SPEI references). page_url is always Makatea's payment page for this order (/pagar/<token>): it works with any provider and its opens are observable — each open emits payment_link.opened (deduplicated per link in a 10-minute window, no personal data) and is counted in opens.count / opens.last_opened_at.
expires_at asks for a validity; it is bounded to what the provider accepts (Stripe 30 min – 24 h, Conekta 1 h – 30 days) and the response carries the real one. Asking for a different validity than the current link's creates a new link.
The link charges the order's open balance (amount − paid − forgiven) in the order's currency. Providers by currency: Stripe, any currency; Conekta, MXN only; Pix, BRL orders of an organization with a Pix key (Pix comes first for BRL, even with Stripe connected; provider: "pix", no expiry). A new link is created when the balance or the currency changed since the current one.
send_via (whatsapp, sms or email) also sends page_url to the member right away, with the same rules as POST /v1/messages (opt-outs, «do not contact», kill switch, send window for WhatsApp/SMS, simulation mode). Nothing is sent without a payment provider for the order's currency (409 no_payment_provider) or for a paid/cancelled order (409 order_not_open). The link is created even if the send fails: the error says why it was not sent.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
send_via | string: whatsapp, sms, email | ||
expires_at | string (date-time) | Desired validity (future). Bounded per provider. |
Respuestas
200OK ·data: PaymentLink400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409comms_disabled— Messaging is turned off for this organization.
do_not_contact — The member is marked «do not contact»: nothing is sent to them.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
no_payment_provider — The organization has no active payment provider.
opted_out — The member opted out of messages.
order_not_open — The operation needs a pending or overdue billing order.
outside_send_window — Outside the organization's send window.
422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
no_recipient — The member has no phone (WhatsApp/SMS) or no email (email).
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.502payment_link_unavailable— The payment provider could not create the link.
send_failed — The channel provider rejected the message.
503channel_unavailable— No connected line for that channel.
Payments
POST /v1/billing-orders/{id}/pay
Settle the whole remaining balance.
Registers one payment for exactly the remaining balance. For partial or historical payments use POST /v1/billing-orders/{id}/payments.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
method | string | Por omisión: "external". | |
type | string | Old name of method. | |
reference | string | ||
notes | string | ||
paid_at | string | When the money was received. Defaults to now. A date without time (2026-09-22) means that day in the organization's timezone (organizations.timezone): today → now, any other day → 12:00 local that day, so it never shifts to the previous day. A date and time without offset (2026-09-22T23:30) is that wall-clock time in the organization's timezone. A full ISO-8601 timestamp with Z or an offset is taken as is. Cannot be in the future. Ejemplo: "2026-09-22". |
Respuestas
200OK ·data: PaymentResult400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409idempotency_in_progress— A request with the same Idempotency-Key is still running. Retry shortly.
order_cancelled — The billing order is cancelled.
order_paid — The billing order is already paid.
payment_voided — The Idempotency-Key belongs to a payment that was voided. A voided payment is not re-applied: send the new payment with a new key. details.payment_id is the voided one.
422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/billing-orders/{id}/payments
Register a payment (partial, historical date, overpayment policy).
excess decides what happens when amount is larger than the balance: reject (default) answers 422 amount_exceeds_balance; credit applies the excess to the member's next open orders (oldest first) and keeps the rest as credit balance.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
amount | number | sí | |
paid_at | string | When the money was received. Defaults to now. A date without time (2026-09-22) means that day in the organization's timezone (organizations.timezone): today → now, any other day → 12:00 local that day, so it never shifts to the previous day. A date and time without offset (2026-09-22T23:30) is that wall-clock time in the organization's timezone. A full ISO-8601 timestamp with Z or an offset is taken as is. Cannot be in the future. Ejemplo: "2026-09-22". | |
method | string | Ejemplo: "transfer". | |
reference | string | ||
notes | string | ||
excess | string: reject, credit | Por omisión: "reject". |
Respuestas
201OK ·data: PaymentResult400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409idempotency_in_progress— A request with the same Idempotency-Key is still running. Retry shortly.
order_cancelled — The billing order is cancelled.
payment_voided — The Idempotency-Key belongs to a payment that was voided. A voided payment is not re-applied: send the new payment with a new key. details.payment_id is the voided one.
422amount_exceeds_balance— The payment is larger than the balance andexcessisreject.
idempotency_key_reused — The Idempotency-Key was already used with a different request body.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
GET /v1/payments
List payments (the ledger).
Every money movement: payments (kind: payment) and reversals of voided payments (kind: reversal, negative amount). allocation says how each entry was applied to its installment (principal, interest, late fee, other charges, unassigned; null when the installment has no breakdown); a reversal carries exactly the same figures, negative. paid_at is when the money was received (it can be in the past); recorded_at is when the entry reached Makatea — created_since/updated_since and the ordering use recorded_at, so a back-dated payment registered today still shows up in your next sync. The ledger is append-only, so updated_since is an alias of created_since. Default order: newest first; with a *_since filter: oldest first.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
member_id | query | string (uuid) | ||
billing_order_id | query | string (uuid) | ||
created_since | query | string (date-time) | Only records created at or after this instant (ISO-8601). Ordering becomes created_at ascending. | |
updated_since | query | string (date-time) | Only records changed at or after this instant (ISO-8601). Switches ordering to updated_at ascending, so you can resume a sync with the last next_cursor. | |
limit | query | integer | ||
cursor | query | string | next_cursor from the previous page. | |
offset | query | integer | Legacy; prefer cursor. | |
count | query | boolean | Include pagination.total. | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: array de Payment400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_cursor — The cursor is malformed or belongs to another ordering. Keep the same filters between pages.
invalid_parameter — A query parameter has an invalid value (not a UUID, not a date, out of range).
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
GET /v1/payments/{id}
Get a payment.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: Payment400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/payments/{id}/void
Void a payment.
Writes a reversal (negative) entry, lowers the order's amount_paid and re-opens it if needed. 409 already_voided the second time.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
reason | string |
Respuestas
200OK ·data: Payment400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409already_voided— The payment was already voided.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
not_voidable — Reversal entries cannot be voided.
422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
Credits (loans)
GET /v1/credits
List credits (loans) with their principal, what came back and what is owed.
Each credit groups the installments of one loan (external_ref = your folio) and carries its principal. totals are to date: capital_recovered/interest_collected/late_fee_collected = what the payment ledger applied to its installments (voided payments net out); capital_outstanding/interest_outstanding = of its open installments with breakdown; balance = amount − paid − forgiven of its open installments; paid_without_ledger = paid amounts imported as history, with no ledger entry. Default order: start_date descending; with updated_since: updated_at ascending.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
member_id | query | string (uuid) | ||
external_ref | query | string | Exact match on your own identifier. | |
updated_since | query | string (date-time) | Only records changed at or after this instant (ISO-8601). Switches ordering to updated_at ascending, so you can resume a sync with the last next_cursor. | |
status | query | string: active, liquidated, cancelled | ||
limit | query | integer | ||
cursor | query | string | next_cursor from the previous page. | |
offset | query | integer | Legacy; prefer cursor. | |
count | query | boolean | Include pagination.total. | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: array de Loan400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_cursor — The cursor is malformed or belongs to another ordering. Keep the same filters between pages.
invalid_parameter — A query parameter has an invalid value (not a UUID, not a date, out of range).
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/credits
Create a credit (loan): generate its installments or attach existing ones.
external_ref (your folio) is unique per organization: reusing it is 409. start_date is when the money was lent: it decides in which period the principal counts as «placed».
Generate the installments with schedule: installments payments, frequency weekly (+7 days), biweekly (+14 days), semimonthly (the 15th and the last day of each month; a first_due_date on another day moves to the next of the two) or monthly (same day each month, or day_of_month; a day the month lacks becomes its last day: Jan 31 → Feb 28 → Mar 31), starting at first_due_date (default: one period after start_date). Amounts: installment_amount each (total = n × amount), otherwise total_amount split in n, otherwise principal split in n. Split exactly to the cent: the first ones get the floor and the last one absorbs the rounding (1,000 / 3 = 333.33 + 333.33 + 333.34). When both principal and total are known each installment carries its capital/interest breakdown (the interest is total − principal, split the same way). Installments are labeled «Pago i de n» and, if the credit has a folio, get external_ref = <folio>-<i>. All or nothing: if they cannot be created the credit is not created either.
Attach existing installments instead by id or external_ref; they must belong to the same member (422 credit_member_mismatch).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
member_id | string (uuid) | sí | |
external_ref | string | Your folio / contract number. Unique per organization. | |
principal | number | sí | Money lent (capital prestado). |
start_date | string (date) | sí | Date the money was lent. |
total_amount | number | Total the member will pay (principal + interest), if you have it. | |
periods | integer | ||
frequency | string: weekly, biweekly, semimonthly, monthly, daily, other | ||
notes | string | ||
billing_order_ids | array de string (uuid) | ||
billing_order_external_refs | array de string | ||
schedule | object | Generate the installments (see the operation description). |
Respuestas
201OK ·data: LoanDetail400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).409conflict— A record with the same unique value (usuallyexternal_ref) already exists.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
422billing_orders_not_found— Some billing orders in the list do not exist (details.missing).
credit_member_mismatch — The credit belongs to another member.
idempotency_key_reused — The Idempotency-Key was already used with a different request body.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
GET /v1/credits/{id}
Get a credit with its installments and their breakdown.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: LoanDetail400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
PATCH /v1/credits/{id}
Update a credit, attach or detach installments.
Only the fields you send change. status can be set to cancelled (the principal stops counting as placed) or back to active; liquidated is computed from its installments.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
external_ref | string, nullable | ||
principal | number | ||
start_date | string (date) | ||
total_amount | number, nullable | ||
periods | integer, nullable | ||
frequency | string: weekly, biweekly, semimonthly, monthly, daily, other, nullable | ||
notes | string, nullable | ||
status | string: active, cancelled | ||
add_billing_order_ids | array de string (uuid) | ||
add_billing_order_external_refs | array de string | ||
remove_billing_order_ids | array de string (uuid) |
Respuestas
200OK ·data: LoanDetail400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409conflict— A record with the same unique value (usuallyexternal_ref) already exists.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
422billing_orders_not_found— Some billing orders in the list do not exist (details.missing).
credit_member_mismatch — The credit belongs to another member.
idempotency_key_reused — The Idempotency-Key was already used with a different request body.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
GET /v1/settings/payment-allocation
How payments are split between late fee, interest and principal.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: AllocationRule400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
PUT /v1/settings/payment-allocation
Change the payment allocation rule.
moratorio_interes_capital (default: late fee, then interest, then other charges, then principal), proporcional (each payment split in proportion to what is owed of each part) or al_liquidar (a partial payment stays «unassigned» until the installment is settled; the settling payment recognizes all of its principal and interest on its date). The rule is fixed on each installment when its breakdown is loaded; with apply_existing: true every installment with breakdown is re-applied with the new rule (past figures change).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
rule | string: moratorio_interes_capital, proporcional, al_liquidar | sí | |
apply_existing | boolean | Por omisión: false. |
Respuestas
200OK ·data: AllocationRule400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).409idempotency_in_progress— A request with the same Idempotency-Key is still running. Retry shortly.422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
Settings
GET /v1/settings/branding
Whether messages and pages carry «Cobrado con Makatea».
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: Branding400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
PUT /v1/settings/branding
Show or hide «Cobrado con Makatea» (on by default).
Controls the footer of collection emails («Cobrado con Makatea · makatea.ai»; other emails say «Enviado con Makatea») and the Makatea mark on the payment page (/pagar/<token>). On by default.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
makatea_branding | boolean | sí |
Respuestas
200OK ·data: Branding400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).409idempotency_in_progress— A request with the same Idempotency-Key is still running. Retry shortly.422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
Webhooks
GET /v1/webhook-endpoints
List webhook endpoints.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: array de WebhookEndpoint400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/webhook-endpoints
Register a webhook endpoint (the signing secret is returned only here).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Cuerpo (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
url | string (uri) | sí | https only; private/internal hosts are rejected. |
events | array de string: *, member.created, member.updated, member.paused, member.resumed, billing_order.created, billing_order.updated, billing_order.paid, billing_order.cancelled, payment.received, payment.voided, payment_link.opened, promise.created, promise.kept, promise.broken, message.sent, message.received, message.classified | sí | |
description | string | ||
api_version | string: 2026-09-23, 2026-09-27 | Version of the event bodies this endpoint receives, frozen at creation. Default: the version of this request. |
Respuestas
201OK ·data: WebhookEndpointCreated400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).409conflict— A record with the same unique value (usuallyexternal_ref) already exists.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
unknown_field — A body field the operation does not accept (API version 2026-09-27 or later). details.field names it.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
DELETE /v1/webhook-endpoints/{id}
Delete a webhook endpoint (its pending deliveries are dropped).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Respuestas
200OK ·data: Deleted400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409idempotency_in_progress— A request with the same Idempotency-Key is still running. Retry shortly.422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
GET /v1/webhook-events
List emitted events (newest first).
Events are recorded only while the organization has at least one active endpoint subscribed to that type.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
type | query | string | ||
created_since | query | string (date-time) | Only records created at or after this instant (ISO-8601). Ordering becomes created_at ascending. | |
limit | query | integer | ||
cursor | query | string | next_cursor from the previous page. | |
offset | query | integer | Legacy; prefer cursor. | |
count | query | boolean | Include pagination.total. | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: array de WebhookEvent400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_cursor — The cursor is malformed or belongs to another ordering. Keep the same filters between pages.
invalid_parameter — A query parameter has an invalid value (not a UUID, not a date, out of range).
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
GET /v1/webhook-deliveries
List delivery attempts (newest first).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
status | query | string: pending, delivered, failed | ||
event_id | query | string (uuid) | ||
endpoint_id | query | string (uuid) | ||
limit | query | integer | ||
cursor | query | string | next_cursor from the previous page. | |
offset | query | integer | Legacy; prefer cursor. | |
count | query | boolean | Include pagination.total. | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: array de WebhookDelivery400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_cursor — The cursor is malformed or belongs to another ordering. Keep the same filters between pages.
invalid_parameter — A query parameter has an invalid value (not a UUID, not a date, out of range).
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
POST /v1/webhook-deliveries/{id}/retry
Retry a delivery now (pending or failed).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Acepta Idempotency-Key.
Respuestas
200OK ·data: WebhookDelivery400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_idempotency_key — Idempotency-Key must be 1 to 255 characters.
invalid_json — The body is not valid JSON, is not an object, or is missing when required.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).404not_found— The resource does not exist in your organization.409already_delivered— The webhook delivery was already delivered.
idempotency_in_progress — A request with the same Idempotency-Key is still running. Retry shortly.
422idempotency_key_reused— The Idempotency-Key was already used with a different request body.
validation_error — A field is missing or has an invalid value. details.field names it.
429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
Operations
GET /v1/sequence-runs
List scheduled/sent collection messages (newest scheduled first).
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
state | query | string | ||
member_id | query | string (uuid) | ||
limit | query | integer | ||
cursor | query | string | next_cursor from the previous page. | |
offset | query | integer | Legacy; prefer cursor. | |
count | query | boolean | Include pagination.total. | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: array de SequenceRun400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_cursor — The cursor is malformed or belongs to another ordering. Keep the same filters between pages.
invalid_parameter — A query parameter has an invalid value (not a UUID, not a date, out of range).
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
GET /v1/flows
List the organization's flows.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: array de Flow400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
GET /v1/templates
List the organization's active templates.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: array de Template400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
GET /v1/stats
Dashboard numbers — the same figures the app's Panel shows.
Every money figure comes from the same database function the app uses (org_metricas_cobranza), so the API and the Panel never disagree. metrics has the full set for the period (from/to, default: 1st of the current month to today, in the org's timezone): collected = money that came in by payment date (voided payments, credit-balance applications and future-dated rows excluded), overdue/upcoming = real balance (amount − paid − forgiven) of open installments due before / on-or-after today, aging by days late (1-9, 10-30, 31-60, 60+), collection_rate = of what came due in the period up to today, the share already paid. metrics.capital_profit splits the same period into principal and profit: placed (principal lent, by credit start_date), collected.capital|interest|late_fee|other|unassigned|no_breakdown|to_credit_balance (they add up exactly to collected.total, the same «collected» as above), profit = interest + late fee collected with its margin over what was collected with a breakdown, outstanding principal and interest (current / overdue) of open installments, and forgiven split into principal (a loss), interest, late fee and other. coverage.status is none when no installment has a breakdown: then every figure is 0 and no_breakdown carries the money. portfolio and members keep their old shape.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
from | query | string (date) | Period start (YYYY-MM-DD). Default: 1st of the current month. | |
to | query | string (date) | Period end (YYYY-MM-DD). Default: today (org timezone). | |
Makatea-Version | header | string: 2026-09-23, 2026-09-27 | Version for this request (default: the one pinned to your key). |
Respuestas
200OK ·data: Stats400invalid_api_version— TheMakatea-Versionheader names a version that does not exist.details.versionslists the valid ones.
invalid_parameter — A query parameter has an invalid value (not a UUID, not a date, out of range).
unknown_parameter — A query parameter the route does not declare. details.allowed lists the valid ones.
401invalid_api_key— The API key (mk_live_…ormk_test_…) does not exist, was revoked or expired.
unauthorized — Missing or invalid credentials.
403insufficient_scope— The API key lacks the scope this operation needs (readfor GET,writefor the rest).429rate_limited— Over the per-minute limit. WaitRetry-Afterseconds. Rejected requests do not count against the limit.500internal_error— Our fault. Safe to retry with the same Idempotency-Key.
Objetos
ErrorBody
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
code | string | sí | Stable code (see «Error codes»). Ejemplo: "validation_error". |
message | string | sí | |
request_id | string | sí | |
details | object | Extra context, e.g. field for validation errors. |
Error
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
error | ErrorBody | sí |
Pagination
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
limit | integer | ||
has_more | boolean | ||
next_cursor | string, nullable | ||
offset | integer | Only when paging with offset. | |
total | integer | Only with count=true. |
Status
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
status | string: ok, degraded | ||
database | string | ||
database_latency_ms | integer | ||
api_version | string | ||
time | string (date-time) |
Member
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string (uuid) | ||
external_ref | string, nullable | ||
full_name | string | ||
first_name | string, nullable | Greeting name ({{member_first_name}}); null = first word of full_name. | |
phone_e164 | string, nullable | ||
email | string, nullable | ||
state | string | ||
identity | object | ||
tags | array de string | ||
notes | string, nullable | ||
payment_reference | string, nullable | ||
segment_id | string, nullable | ||
promised_date | string (date), nullable | ||
promise_status | string | ||
promised_amount | number, nullable | ||
promise_registered_at | string (date-time), nullable | ||
credit_balance | number | ||
do_not_contact | boolean | Never message this member (withdraws anything queued). | |
do_not_contact_reason | string, nullable | ||
customer_since | string (date), nullable | When it became your customer; created_at is when it entered Makatea. | |
import_batch_id | string (uuid), nullable | ||
paused_until | string (date-time), nullable | Collection paused until this instant (in the past = not paused). | |
pause_reason | string, nullable | ||
paused_at | string (date-time), nullable | ||
created_at | string (date-time) | ||
updated_at | string (date-time) |
BillingOrder
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string (uuid) | ||
member_id | string (uuid) | ||
external_ref | string, nullable | ||
amount | number | ||
amount_paid | number | ||
amount_forgiven | number | ||
late_fee | number | ||
balance | number | amount − amount_paid − amount_forgiven (late fees are reported apart). | |
currency | string | ||
due_date | string (date) | ||
period_label | string, nullable | ||
status | string: pending, overdue, paid, cancelled | ||
paid_at | string (date-time), nullable | ||
paid_via | string, nullable | ||
notes | string, nullable | ||
forgiven_at | string (date-time), nullable | ||
forgiven_reason | string, nullable | ||
cancel_reason | string, nullable | Why it was cancelled (DELETE …?reason=). | |
created_at | string (date-time) | ||
updated_at | string (date-time) | ||
transferred_to_order_id | string (uuid), nullable | Installment its balance was transferred to (POST …/transfer); set only on cancelled orders. | |
credit_id | string (uuid), nullable | Credit (loan) it belongs to. | |
capital_portion | number, nullable | Principal part of the installment (null = no breakdown). | |
interest_portion | number, nullable | Interest part of the installment. | |
breakdown | object, nullable | null when the installment has no breakdown (figures are never invented). |
Payment
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string (uuid) | ||
billing_order_id | string (uuid) | ||
member_id | string (uuid) | ||
amount | number | ||
kind | string: payment, reversal | ||
method | string, nullable | ||
reference | string, nullable | ||
notes | string, nullable | ||
voids_payment_id | string (uuid), nullable | ||
voided | boolean | ||
paid_at | string (date-time) | When the money was received. | |
created_at | string (date-time) | ||
recorded_at | string (date-time) | When the entry was recorded in Makatea. | |
allocation | object, nullable | How this entry was applied to its installment. Adds up to amount. unassigned = beyond the installment's parts or, with rule al_liquidar, a partial payment not yet recognized (the settling payment then carries it negative). null when the installment has no breakdown. |
TransferResult
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
already_transferred | boolean | ||
from | BillingOrder | ||
to | BillingOrder |
PaymentResult
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
order_id | string (uuid) | ||
amount_paid | number | ||
status | string | ||
fully_paid | boolean | ||
excess_applied_to_other_orders | number | ||
credit_added | number | ||
already_applied | boolean | ||
payment_id | string (uuid), nullable | The ledger entry of this call (or the original one when already_applied). | |
payment | Payment | ||
order | BillingOrder |
PromiseState
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
member_id | string (uuid) | ||
status | string: none, active, kept, broken, cancelled | ||
current | object, nullable | ||
history | array de object |
Credit
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
member_id | string (uuid) | ||
credit_balance | number | ||
ledger | array de object |
CreditApplied
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
member_id | string (uuid) | ||
applied | number | ||
credit_balance | number |
Interaction
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string (uuid) | ||
channel | string | ||
direction | string: inbound, outbound | ||
text | string, nullable | ||
attachment | string, nullable | ||
classification | string, nullable | ||
sequence_run_id | string (uuid), nullable | ||
simulated | boolean | ||
occurred_at | string (date-time) |
MessageResult
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string (uuid) | ||
object | string: interaction, sequence_run | ||
status | string: sent, simulated, queued, queued_simulated | ||
channel | string | ||
member_id | string (uuid) |
ConversationImportResult
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
inserted | integer | ||
skipped_duplicates | integer | ||
unmatched | array de object | ||
errors | array de object |
Document
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string (uuid) | ||
member_id | string (uuid) | ||
name | string | ||
type | string | ||
mime_type | string | ||
size | integer | ||
external_ref | string, nullable | ||
description | string, nullable | ||
storage_path | string | ||
download_url | string, nullable | Signed URL, valid 1 hour. | |
download_url_expires_at | string (date-time), nullable | ||
created_at | string (date-time) |
Deleted
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string (uuid) | ||
deleted | boolean |
PaymentLink
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
url | string, nullable | Provider link (Stripe Checkout) or Makatea's page (OXXO/SPEI). null without a provider (reason). | |
expires_at | string (date-time), nullable | Real validity (bounded per provider). | |
expires_at_requested | string (date-time) | Only when you sent expires_at. | |
provider | string, nullable | ||
reason | string | Why there is no url (no_provider, order_closed, …). | |
page_url | string | Makatea's payment page for this order; its opens emit payment_link.opened. | |
opens | object | ||
sent | object, nullable | Only with send_via. |
Branding
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
makatea_branding | boolean | true = «Cobrado con Makatea» in collection emails and on the payment page. |
WebhookEndpoint
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string (uuid) | ||
url | string | ||
events | array de string | ||
active | boolean | ||
description | string, nullable | ||
webhook_version | string | Version of the event bodies it receives (frozen). | |
created_at | string (date-time) | ||
updated_at | string (date-time) |
WebhookEndpointCreated
object
WebhookEvent
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string (uuid) | ||
type | string: member.created, member.updated, member.paused, member.resumed, billing_order.created, billing_order.updated, billing_order.paid, billing_order.cancelled, payment.received, payment.voided, payment_link.opened, promise.created, promise.kept, promise.broken, message.sent, message.received, message.classified | ||
created_at | string (date-time) | ||
data | object |
WebhookDelivery
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string (uuid) | ||
event_id | string (uuid) | ||
event_type | string | ||
endpoint_id | string (uuid) | ||
status | string: pending, delivered, failed | ||
attempts | integer | ||
next_attempt_at | string (date-time), nullable | ||
last_status | integer, nullable | ||
last_error | string, nullable | ||
created_at | string (date-time) | ||
delivered_at | string (date-time), nullable |
SequenceRun
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string (uuid) | ||
member_id | string (uuid) | ||
billing_order_id | string (uuid), nullable | ||
template_id | string (uuid) | ||
state | string | ||
channel | string | ||
scheduled_at | string (date-time) | ||
outcome | string, nullable | ||
attempts | integer |
Flow
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string (uuid) | ||
name | string | ||
status | string | ||
steps | integer | ||
type | string, nullable | ||
anchor | string, nullable | ||
audience_mode | string | members = explicit list (enroll/remove by API); otherwise all, active, states, tags, segments, auto_obligation. | |
role | string: general, segment, suggestion, nullable | Collection calendars only. general = the account's one general calendar (every client with an open charge not covered by a tag calendar); segment = applies to clients with its tags; suggestion = left by Makatea, never sends and cannot be activated until it is made the general calendar in the app. null for other flows. |
FlowMembership
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
flow_id | string (uuid) | ||
member_id | string (uuid) | ||
enrolled | boolean | ||
changed | boolean | false when it was already so. | |
flow_status | string | ||
runs_created | integer | ||
runs_withdrawn | integer |
PauseState
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
member_id | string (uuid) | ||
paused | boolean | ||
paused_until | string (date-time), nullable | ||
pause_reason | string, nullable | ||
paused_at | string (date-time), nullable | ||
runs_rescheduled | integer | Only on resume. |
Template
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string (uuid) | ||
name | string | ||
channel | string | ||
trigger_type | string | ||
version | integer | ||
subject | string, nullable |
Stats
object
Loan
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
id | string (uuid) | ||
member_id | string (uuid) | ||
member_name | string, nullable | ||
external_ref | string, nullable | Your folio. | |
principal | number | Money lent. | |
total_amount | number, nullable | ||
periods | integer, nullable | ||
frequency | string, nullable | ||
start_date | string (date) | Date the money was lent. | |
status | string: active, liquidated, cancelled | ||
notes | string, nullable | ||
schedule | object, nullable | How Makatea generated its installments (null = attached by hand). | |
created_at | string (date-time) | ||
updated_at | string (date-time) | ||
totals | object |
SplitResult
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
parent | BillingOrder | ||
children | array de BillingOrder |
LoanDetail
object
BatchResult
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
object | string: batch | ||
dry_run | boolean | ||
batch_id | string (uuid), nullable | import_batch_id stamped on the records (null for dry runs and payment batches). | |
summary | object | ||
results | array de object |
AllocationRule
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
rule | string | ||
rules | array de string | ||
orders_reapplied | integer |