Payment intents
A payment intent guides the lifecycle of a payment. Use exactly one intent per payment to keep traceability clear.
Related API reference
- Create a payment method
- Peru merchant account requirement
- Create a payment intent
- Confirm a payment intent
- Retrieve a payment intent
- Capture a payment intent
- Cancel a payment intent
- List all payment intents
Basic flow
- Create or collect a payment method for the buyer.
- Create a payment intent with the amount and currency.
- Confirm the intent using the
paymentMethodId. - Listen for webhooks before marking the payment as complete in your system.
Create a payment method
Create the payment method client-side with a publishable key. For cards, the response returns an id that you later send as paymentMethodId when confirming the intent from your server.
Peru merchant account requirement
For merchant accounts created in Peru, the customer attached to the payment method must have an email address when creating payment methods.
You can meet this requirement in two ways:
- Send
customer.emailin the payment method creation payload to create and attach the customer in the same request. - Send the
customerIdof a customer previously created with theemailattribute.
Card example and validation rules
curl https://api.onvopay.com/v1/payment-methods \
-X POST \
-H "Authorization: Bearer $ONVO_PUBLISHABLE_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "card",
"card": {
"number": "4242424242424242",
"expMonth": 12,
"expYear": 2028,
"cvv": "123",
"holderName": "Maria Rodriguez"
},
"billing": {
"name": "Maria Rodriguez",
"address": {
"country": "CR"
}
},
"customer": {
"name": "Maria Rodriguez",
"email": "maria@example.com"
}
}'
To avoid 400 validation errors before the card is tokenized, validate these fields in your form:
card.holderName: non-empty text.card.number: a digits-only string, without spaces or separators, and a number that passes Luhn validation.card.expMonth: integer between1and12.card.expYear: integer between2023and2100. Also validate that the card is not expired before sending it.card.cvv: string with3or4digits when you send it.
If the payload does not meet these rules, ONVO responds with 400 and a validation error. For example, an invalid card number can return:
{
"statusCode": 400,
"message": ["card.number Card number is invalid"],
"error": "Bad Request"
}
When you create a card payment method, ONVO tokenizes and verifies the card before creating the object. If tokenization fails because the card details are invalid, the endpoint responds with 400 and no payment method is created.
{
"code": "cards.invalid_card_info",
"path": "/v1/payment-methods",
"type": "OnvoAPIError",
"message": "There was an error with the card information provided. Please review card number, expiration date and cvv",
"timestamp": "2026-04-29T17:36:28.477Z",
"statusCode": 400
}
Show the message to the buyer and ask them to review the card number, expiration date, and CVV before trying to create the payment method again.
Create an intent
curl https://api.onvopay.com/v1/payment-intents \
-X POST \
-H "Authorization: Bearer $ONVO_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 500000,
"currency": "CRC",
"description": "Order #1001"
}'
Confirm the intent
Use the intent id and the id from the payment method created earlier.
curl https://api.onvopay.com/v1/payment-intents/$PAYMENT_INTENT_ID/confirm \
-X POST \
-H "Authorization: Bearer $ONVO_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"paymentMethodId": "cl502zv0d0127ebdp3zt27651"
}'
Common states
| State | Meaning |
|---|---|
requires_payment_method | Initial state. The intent also stays in this state if confirmation fails, for example because a card is declined. |
requires_action | The payment method needs an additional buyer action, such as 3DS authentication. |
processing | ONVO is processing the payment. |
succeeded | The payment succeeded. |
canceled | The intent was canceled. |
Best practices
- Store the intent
idwith your payment. - Use
metadatafor internal cart, payment, or customer IDs. - Confirm the final state by webhook before delivering digital goods or marking the payment as complete.