Skip to content
ESENGo to the Portal

Operations and errors

Environments, go-live checklist, usage limits, errors by endpoint and downloads for the Integration API.

The reference data for running your integration: environments, limits, errors and downloads.

Environments and URLs

Your integration has two environments, Sandbox and Production, with their own credentials. You manage both from the same portal, chytapay.com.ar/portal/login, with the environment selector.

Service Sandbox Production
Integration API (charges, bulk, payer-lookup) https://integration-api.test.chytapay.com.ar https://integration-api.chytapay.com.ar
Auth API (OAuth: /integration/oauth2/*) https://auth-api.test.chytapay.com.ar https://auth-api.chytapay.com.ar
Widget publishable key pk_test pk_live

The Integration API mounts its routes at the root: /payment-request, /payment-request/bulk and /payer-lookup. The widget uses /v1/payments on the same host.

Test tokens, the test webhook and payment simulation exist only in Sandbox. In Production, livemode is true only for a real payment.

Going live

You request Production under Credenciales (Credentials): if the automatic check approves it, you generate the production credentials with the environment selector on Production, and if not, the request goes to review. Nothing from Sandbox carries over. Before you collect, check:

  1. Credentials. Generate them under Credenciales (Credentials) and use your production clientId and clientSecret against auth-api.chytapay.com.ar, and the pk_live if you use the widget (the sk_live only if you create charges through /v1/payments).
  2. Linked merchants. Sandbox links don't exist in production: each merchant repeats the OAuth flow in Connect merchant accounts.
  3. Webhooks. Set the URL under Configuración (Settings) with the environment on Production, verify the signature with the production secret, and enable payment.unmatched if you need it, since it's opt-in. See delivery guarantees and subscriptions.
  4. Errors. Handle 409, 429 and timeouts with the retries table.
  5. Tokens and events. Renew each merchant account's idToken with the refreshToken before the hour is up, deduplicate by X-Chytapay-Webhook-Id and return 2xx within 5 seconds.

Retries on your side

There is no idempotency key. The referenceId prevents duplicates: it's unique per integration and merchant account, canceled charges included.

Situation What to do
Timeout or 5xx on a create GET /payment-request/{referenceId}: on 404, retry with the same referenceId.
409 ReferenceIdAlreadyExists It was already created. Retrieve it with GET; don't generate a new referenceId.
429 on create or bulk Don't retry in a loop: wait until 00:00 Argentina time. A bulk that doesn't fit entirely under the cap creates nothing.
Timeout or 5xx on a bulk Retrieve one referenceId from the batch with GET: bulk is all or nothing.
422 on a retried bulk If the reason is The referenceId already exists for this integration, the earlier batch was created.
503 on payer-lookup ARCA didn't respond. Retry, or continue without validating the payer.

The create example with timeout and 409 is in Create charges.

Limits

The only daily cap when creating charges is the WhatsApp message cap. There is no cap on requests or on charges created per day. It resets at 00:00 Argentina time (UTC-3).

Cap Value When exceeded
Your integration's messages Per integration, all its merchants added together: 20 per day in Sandbox and 200 initial per day in Production. Raise it with Pedir más límite (Request more limit), on the portal Dashboard. 429 IntegrationDailyRequestLimitExceededError
Messages shared across integrations One global daily cap 429 IntegrationGlobalDailyMessageLimitExceededError

What counts as a WhatsApp message

Each charge created with sendWhatsappNotification: true counts as one message. Charges that don't ask for a WhatsApp notification don't use the cap. A bulk that doesn't fit entirely under the cap creates nothing.

The 429 response from the message caps

The body carries code (which of the two caps) and message. Your integration's cap adds availableAt (the reset, in Argentina time), maxRequestsPerDay and maxMessagesPerDay. The global one adds requestedMessages and availableAtUnixSeconds (the reset, in Unix seconds). If the cap can't be checked, create and bulk answer 503 IntegrationDailyLimitUnavailableError: retry in a few minutes. The reset is at 00:00 Argentina time: don't retry in a loop, wait until then. With parallel creates near the cap, a charge can be created even though it returned 429: check with GET before recreating it.

Other limits

Limit Value When exceeded
Items per bulk 1 to 100 per call 400 ValidationError
CVU pool, per merchant account Up to 100 per merchant account 400 InsufficientActiveAccountsError

Payer-lookup

GET /payer-lookup?document= has its own quota, separate from the creation caps: 1000 units per day, per integration and merchant account, reset at 00:00 Argentina time. A CUIL or CUIT costs 1 and a DNI costs 2, because Chytapay queries ARCA for both possible CUILs. When exceeded, 429 PayerLookupDailyLimitExceededError.

  • Don't consume: a 400 for an invalid document, and a 503 answered without querying ARCA.
  • Do consume: a 200 with name: null, and a 503 because ARCA didn't respond.
  • The 429 includes code, message, availableAtUnixSeconds (the reset, in Unix seconds) and maxLookupsPerDay (1000).

See how to validate the payer.

CVU pool

The pool belongs to the merchant account, is shared by all its integrations and is taken up by the CVUs of open charges. If no CVU is free, create and bulk return 400 InsufficientActiveAccountsError and create nothing. When a charge closes, its CVU goes back to the pool. See how this affects each mode in Reconciliation.

Errors by endpoint

Decide by the HTTP status, then by code or error, never by the text of message. The tables follow the OpenAPI spec.

Show the error body shapes

Error body format

There is no request id header. The id comes in the body, only in the general shape: log it. Most messages are in English.

Body shape When
{ code, message, id } General shape: business 400, 409 CustomerAlreadyAssociatedError, 500
{ code, message, id, validationDetails } 400 ValidationError. validationDetails is a list of { field, message }; message repeats the first one.
{ error, message, referenceId } 409 from create
{ message, errors } 422 from bulk. errors is a list of { index, referenceId, reason }.
{ error, message, data } 409 from PATCH, payer PATCH and cancel
{ message } 404 for a nonexistent charge, an integration not ready to collect or a location
{ code, message } 503 from payer-lookup
Plain text, not JSON 400, 403 and 404 from the token check

Common to all endpoints

HTTP Body When it happens and what to do
401 Missing, invalid or expired token. Renew it with the refresh token from Connect merchant accounts.
400 Bad request: Missing required authentication data The token doesn't carry the account, role or application. Send the merchant's id_token in Authorization: Bearer.
404 Integration client not found The token belongs to another application. Request it with your integration's clientId in that environment.
403 Not authorized as user of integration client The merchant account isn't linked, or was unlinked. Link it through OAuth.
500 { code, message, id } Internal error. On a create or bulk, check with GET before retrying.

Create a charge: POST /payment-request

HTTP code or error When it happens and what to do
400 ValidationError A field is missing, has an invalid type or range, or this type doesn't accept it. See validationDetails.
400 WebhookUrlBlockedError webhookUrl points to an internal or private address.
400 InsufficientActiveAccountsError No free CVU in the merchant's pool.
409 ReferenceIdAlreadyExists The referenceId already exists, even if that charge is canceled. The charge isn't returned: retrieve it with GET.
429 IntegrationDailyRequestLimitExceededError or IntegrationGlobalDailyMessageLimitExceededError You reached the WhatsApp message cap. See the limits.
409 CustomerAlreadyAssociatedError Two simultaneous creates for the same payer collided. Check with GET and retry if it doesn't exist.

Create charges in bulk: POST /payment-request/bulk

If the bulk fails, no charge in the batch is created.

HTTP code When it happens and what to do
400 ValidationError Empty batch or more than 100 items, an item breaks the contract, or a due date has a time (only YYYY-MM-DD). See validationDetails.
400 InsufficientActiveAccountsError The merchant's pool isn't large enough for the batch.
404 The integration isn't ready to collect and retrying won't fix it. Contact support.
429 IntegrationDailyRequestLimitExceededError or IntegrationGlobalDailyMessageLimitExceededError The batch doesn't fit entirely under the WhatsApp message cap: nothing is created.
422 Items that fail business validation, all listed in errors. Fix them and resend the full batch.

The 422 reason values are Duplicate referenceId within the batch, The referenceId already exists for this integration, The taxDocument does not resolve to a valid CUIL and Duplicate payer within the batch (the same document in more than one item).

Retrieve a charge: GET /payment-request/{referenceId}

HTTP Body When it happens and what to do
404 { "message": "Payment request not found" } No charge with that referenceId for this integration and merchant account. Check that the token belongs to the right merchant.

Set the amount: PATCH /payment-request/{referenceId}

HTTP code or error When it happens and what to do
400 ValidationError amount is missing, isn't positive, has more than 2 decimals or exceeds 200,000,000.
404 The charge doesn't exist.
409 PaymentRequestCannotBeModified The charge isn't in draft, or already received payments: only a draft with no payments accepts PATCH.

Correct the payer: PATCH /payment-request/{referenceId}/customer

HTTP code or error When it happens and what to do
400 ValidationError taxDocument is missing or invalid (format or check digit), or name, email or phoneNumber break the contract.
404 The charge doesn't exist, or the integration isn't ready to collect.
409 PaymentRequestCustomerCannotBeModified The payer can't be changed. The reason is in data.reason.
Show the data.reason values
data.reason Meaning
conciliation_type_not_cuil The charge uses CVU mode, which doesn't store the payer's document.
state_not_modifiable The charge is in a final state.
payment_already_received The charge already received money.
no_collision_free_account No CVU can hold the new document. Nothing was changed.
missing_notification_contact The new payer lacks the contact the reminders require.
incomplete_payment_request_data The charge has no associated payer.
concurrent_modification A concurrent change. Read the charge again and retry.

See when to use it in correct the payer.

Cancel a charge: POST /payment-request/{referenceId}/cancel

HTTP error When it happens and what to do
404 The charge doesn't exist.
409 PaymentRequestCannotBeCanceled The charge isn't in draft or pending: it has partial payments, or it's paid, expired or canceled.

Validate a document: GET /payer-lookup

HTTP code When it happens and what to do
200 with name: null ARCA responded and the document has no holder. Ask the payer to check it.
400 ValidationError document isn't an 11-digit CUIL or CUIT, or a 7 or 8-digit DNI.
404 The account isn't linked.
429 PayerLookupDailyLimitExceededError You reached the 1000 units for the day.
503 PayerLookupProviderUnavailableError ARCA couldn't be queried: the payer wasn't verified. Retry, or continue without validating.
503 PayerLookupQuotaUnavailableError The quota couldn't be checked. Retry.

Assign the location: PUT /my-integration/tenant

HTTP Body When it happens and what to do
400 ValidationError tenantKey is missing or empty.
404 { "message": "The specified tenant does not exist or was deleted" } The location doesn't exist, was deleted or belongs to another integration. See Locations.
404 { "message": "No integration account was found for the authenticated user" } The merchant account isn't linked.

OAuth

The errors for authorize, token, refresh and revoke are in Connect merchant accounts.

Common mistakes

  • Using the wrong token. The Integration API takes the merchant account's id_token, not the integration admin's token or the clientSecret.
  • Recreating after a timeout or retrying a 429 in a loop. See retries and the 429 response.
  • Reading name: null as an ARCA failure. The document has no holder; the failure is the 503.

Downloads

OpenAPI

Import the spec into Postman, Insomnia, Bruno or any API client, or browse the API Reference:

  • Integration API: https://public-api.chytapay.com.ar/integration-api-swagger
  • Auth API: https://public-api.chytapay.com.ar/auth-api-swagger

The spec still declares 10,000,000 as the amount cap for PATCH; the API enforces 200,000,000.

Postman collection

It includes a Sandbox environment (the file is named Test) and a Production one, with the hosts set. It covers all the charge endpoints, payer-lookup and payer correction, with example dates that are always in the future.

  • Collection: /api/assets/postman/Chytapay-Integration-API.postman_collection.json
  • Test environment: /api/assets/postman/Chytapay-Test.postman_environment.json
  • Production environment: /api/assets/postman/Chytapay-Production.postman_environment.json

Frequently asked questions

Are the limits and the pool per merchant or per integration?

The message cap is per integration (all its merchants added together). The payer-lookup quota is per integration and merchant account. The CVU pool is per merchant account. More answers in Frequently asked questions.