Skip to main content
The objects the SDK hands back to your app: the final status of a transaction, and the one-time token when you create the payment from your backend.
The status object reports how the transaction ended. The SDK delivers it through onStatus.

What you receive

The payload carries three pieces:
  • status: passed through exactly as the backend returns it, for the statuses this SDK version knows. On Web those are (payments: CREATED, SUCCEEDED, PENDING, DECLINED, REJECTED, CANCELED, ERROR, EXPIRED, REFUNDED, VERIFIED, READY_TO_PAY; enrollments: ENROLLED, ENROLL_IN_PROCESS, UNENROLLED, UNENROLL_IN_PROCESS, READY_TO_ENROLL, CREATED, PENDING, DECLINED, REJECTED, CANCELED, ERROR, EXPIRED). On every platform, any other value arrives as INTERNAL_ERROR with message.code UNSUPPORTED_STATUS and message.reason set to unsupported status: <value>.
  • substatus: passed through exactly as the backend returns it. On Web an empty or missing substatus arrives as null.
  • message: extra context. Its shape depends on the source:
On Web every other payment status, and every enrollment status, carries message: null.

Statuses emitted by the SDK itself

Two statuses are not relayed from the backend, the SDK emits them locally:
  • INTERNAL_ERROR: raised when a backend service call failed, or when something failed inside the SDK (load, view rendering, network, unexpected exception).
  • USER_CANCEL: raised when the user closes a form or view without completing the flow.
On Web, INTERNAL_ERROR with message.code FORM_INVALID is not final. The SDK raises it when you submit a form that is not valid, with transaction.submit() or with transaction.start({ paymentMethod }) on the payment methods list. The form stays mounted and the user can correct it.On Web the message.code values for source: "sdk" include:
  • UNSUPPORTED_STATUS. The backend returned a status the SDK does not know. message.reason is unsupported status: <value>.
  • FORM_INVALID. The submitted form is not valid. Not final.
  • ELEMENT_NOT_FOUND. The element passed to paymentMethodList.mount() is not in the DOM, or the form’s container was removed while the form was loading. A config elementSelector that matches nothing makes start() reject with elementSelector "<selector>" was not found in the document. instead.
  • COLLECT_FAILED. In manual mode (you pass createPayment), the Mercado Pago wallet failed to collect the payment data. message.reason starts with MERCADO_PAGO_.
  • UNEXPECTED_ERROR. A failure the SDK does not classify. message.reason carries the error message.
On iOS the message.code values for source: "sdk" are these. message.context names the call site that produced the error.On Web a cancel during a 3DS challenge, for example closing the challenge or pressing the browser back button, arrives as status: "PENDING" with substatus: "USER_CANCEL" and message: null, because the payment already exists on the backend. Calling transaction.unmount() on a started transaction that has not delivered a status also emits USER_CANCEL, unless a payment is in flight.

Backend failure or SDK failure? Read message.source

INTERNAL_ERROR covers both cases, so the status alone does not tell you where the failure came from. A backend rejection (for example, an invalid or expired checkout session) arrives as:
An SDK-side failure (network, rendering, unexpected exception) arrives as:
On Web, reason is the backend’s messages[], message or description. For INVALID_CHECKOUT_SESSION the SDK appends a hint that a headless transaction needs a session created with workflow SDK_SEAMLESS.When message.source is "backend", Yuno’s API rejected a call: code and raw carry the backend’s own error, so start debugging there (session validity, workflow, credentials). When it’s "sdk", the failure originated inside the SDK and context names the module or call site that produced it.

Backend status values

The set of possible status and substatus values is defined by the backend. See the workflow reference for each flow: