Skip to main content
API contract revision
This version makes input validation stricter and fixes several responses so they match what is documented. Review the list of changes that can affect your integration first.

Changes that can affect your integration

These are changes where a request that used to pass (or returned 5xx) now returns 4xx, or where a response value your code might be reading changes.
  • Strict booleans in POST /v2/debts and POST/PATCH /subscriptions: allowOverduePayment, allowPartialPayments, autopay, and enforcePaymentOrder only accept true/false. "true", 1, etc. return 400 with details[]. description must be a string (400). See API conventions.
  • additionalData in POST /v2/debts, POST /payment-links, and POST/PATCH /subscriptions: it must be a flat object and cannot use reserved keys (description, paymentMethods, productName, etc.). Otherwise, 400. See API conventions.
  • POST /payment-links: an externalClientId that does not match a contact returns 422 BUSINESS_RULE_VIOLATION (the link used to be created anyway). See Payment links.
  • POST/PATCH /payment-links: expiresAt must be an RFC 3339 date-time (2026-12-31 23:59 or a date alone return 400). In the PATCH, expiresAt: null returns 400 (it used to be 500; links always expire), metadata null or not an object returns 400, and an empty description returns 400. See Payment links.
  • PATCH /subscriptions/{id}: validates types, the paymentMethods enum, and the exclusion between autopay: true and paymentMethods (400). A CANCELLED or ENDED subscription returns 422 (it used to be 200). See Subscriptions.
  • POST /subscriptions: intervalUnit is case-sensitive (MONTH returns 400) and, if the scheduling is invalid, neither the product nor the inline contact is created. See Subscriptions.
  • PATCH /contacts/{id}: phones: [] returns 400 (it used to be 200 with no effect). See Contacts.
  • GET /contacts: identifier and externalClientId with different values return 400. See Contacts.
  • GET /products: an active value other than true/false returns 400 (it used to be read as false). See Products.
  • GET /payment-links: createdAtFrom/createdAtTo with an invalid format return 400 (they used to be compared as text). See Payment links.
  • GET /subscriptions: externalClientId now filters (it used to be ignored and returned subscriptions of other contacts). Empty or blank returns 400. See Subscriptions.
  • GET /debts/{id}, PATCH /debts/{id}, POST /debts/{id}/cancel: a canceled debt can be read (200, status: CANCELLED); canceling it again or sending a PATCH returns 422 (it used to be 404). See Debts.
  • POST /v2/debts: new value autopayReason: "NO_PRODUCT". If you validate autopayReason against a closed list, add it. See Direct debit.
  • Dates in contacts, debts, and link payments: date-time values are returned in UTC with milliseconds and Z (2026-09-24T21:09:41.835Z). They used to come without a zone, with +00:00, or with microseconds. See API conventions.
  • PATCH /debts/{id}: dueDate in the response becomes YYYY-MM-DD (it used to be a date-time). See Debts.
  • POST /payment-links without a debtor: paymentUrl becomes the short URL (it no longer contains the identifierValue) and can be null if its generation fails. Treat it as an opaque URL. See Payment links.
  • Payment links, every response: expiresAt is always returned in UTC with milliseconds and Z (2026-12-31T23:59:59.000Z), even if it was sent with an offset (-06:00). Older links stored with a date alone (2026-12-01) come out as the start of that UTC day (2026-12-01T00:00:00.000Z). See Payment links.
  • Payment links without an external key, all responses: externalPaymentLinkId is null when the link was created without externalPaymentLinkId or an Idempotency-Key header (it used to return a plk_<uuid> value equal to the paymentLinkId). See Payment links.
  • GET /debts and GET /payment-links/{id}/payments: createdAtTo as a date alone now includes that day (it used to filter up to its start). If you sent the next day to compensate, you now get one extra day. createdAtFrom later than createdAtTo returns 400 with the message createdAtFrom must be earlier than or equal to createdAtTo. See Debts.

Fixes

  • PATCH /debts/{id} and PATCH /subscriptions/{id}: the PATCH no longer resets allowPartialPayments to false, and amountPaid comes out correctly (not null). See Debts.
  • GET /debts/{id} and GET /debts: description appears in reads. See Debts.
  • POST /v2/debts and POST /subscriptions: contact.contactId comes with the con_ prefix also when the contact is created inline. See Direct debit.
  • GET /contacts: identifier filters, and contactCode accepts the con_ prefix. See Contacts.
  • Contacts: contacts without an email created inline return email: null (it used to be the text "null"), also when reading existing ones. See Contacts.
  • GET /payment-links?externalPaymentLinkId=: no longer returns 500. See Payment links.
  • POST /payment-links: a repeated externalPaymentLinkId returns 409 without creating the debt. A link with a debtor no longer fails with 500 if the portal configuration does not respond. See Payment links.
  • PATCH /payment-links/{id}: expiresAt also updates the due date of the link’s debt. If that debt was already cancelled, only the link is updated (the PATCH used to fail). See Payment links.
  • Payment link response: always carries externalPaymentLinkId, expiresAt, successUrl, metadata, identifierValue, contact, and product, with null when there is no value. See Payment links.
  • POST /products: returns what was stored (timestamps, externalProductId, active) instead of echoing the request. See Products.
  • PATCH /products/{id}: active: false deactivates the product; renaming to a name already in use, including one used by an inactive product, returns 409 (it used to be 500); invalid types return 400 (they used to be 500). See Products.
  • POST /subscriptions: paymentUrl is no longer null, and scheduling.billingDay is inferred from startDate (for month and year). See Subscriptions.
  • GET /debts and GET /payment-links/{id}/payments: createdAtFrom/createdAtTo accept an RFC 3339 date-time in addition to a date. The same date in both returns that day’s debts (it used to be 400), and a future createdAtFrom without createdAtTo returns an empty page (it used to be 400). See Debts.
  • PATCH of contacts, products, payment links, subscriptions, and debts: companyCode in the body is taken as context and is no longer rejected as a non-editable field. See API conventions.
  • POST /v2/debts (batch): each error in details[] carries field. See Direct debit.
  • PATCH /debts/{id}: impossible dates (2026-02-30) return 400. See Debts.
  • POST /v2/debts, POST /payment-links, and subscriptions: additionalData sent as an object is stored on the debt (it used to be lost in debts and links). See API conventions.
  • PATCH /subscriptions/{id}: if updating one of the subscription’s debts fails, the response is 207 with error.code: PARTIAL_UPDATE (it used to be 500 INTERNAL_ERROR). The subscription is updated. See Subscriptions.
  • paymentUrl in debts, subscriptions and payment links: if your company has no private links configuration, paymentUrl is no longer null: it returns your company’s portal URL. Still treat it as an opaque URL. See Debts.