PayPal via API
This page explains the steps necessary to integrate PayPal using the DEUNA API.
1. Create an order_token
order_token
To make a purchase, you must create a DEUNA order.
Follow the steps to Create an Order.
The API returns an order_token
that is used throughout the entire flow.
2. Create user
Create a user with DEUNA to get an authorization token to perform the purchase later.
Follow the API Reference to create the user.
The API returns a user token
which is required to follow the next steps.
OTP is recommended to get a new token each time a customer confirms through the SMS or Email the code. You can use an External Authentication login to manage the user auth tokens by your own without request them the OTP. Talk to your Sales Engineer for further guidance.
If the email used already exists:
- The API returns the message
user already exists
. - Request the OTP and login with the OTP to obtain a fresh user
token
. - Now the user
token
can be used.
3. Get payment methods
Confirm the payment methods to obtain the PayPal Wallet configuration.
Follow the stepsGet Payment Methods.
Request
curl --location '{{base_url}}/merchants/orders/{{order_token}}/payments-methods' \
--header 'x-api-key: {{merchant_private_key}}' \
--header 'Authorization: Bearer {{user_token}}'
Response
{
"data": [
{
"enabled": true,
"method_type": "wallet",
"processor_name": "paypal_wallet", // PayPal Wallet identifier
"exclude_cvv": false,
"stored_payment_methods": [
{
"payment_method": "adb1ef51-e073-49f5-ba3b-a7e42344fd15",
"account_identifier": "[email protected]"
}
],
"id": "58745b8e-7127-44ea-84ef-656b3ffc611b", // Payment method ID
"authorization": {
"required": true, // true | false
"flow": "consent"
}
}
]
}
Purchase flow
Depending on the response obtained from Get Payment Methods, align with one of each flow to complete a purchase:
Without vaulting
Use it when tokenization of a PayPal account is not required to complete the purchase.
The response from Get Payment Methods would be as follows:
{
"data": [
{
"enabled": true,
"method_type": "wallet",
"processor_name": "paypal_wallet", // PayPal Wallet identifier
"exclude_cvv": false,
"stored_payment_methods": [],
"id": "58745b8e-7127-44ea-84ef-656b3ffc611b", // Payment method ID
"authorization": {
"required": false,
"flow": "consent"
}
}
]
}
1. Perform the purchase
- Make a V1 Purchase.
Here is a list of required fields for PayPal Wallet:
Field | Description | Value |
---|---|---|
specific_fields.callbacks.on_success | Redirect URL after authorizing the purchase with your PayPal Wallet account. | https://example.com/ |
method_type | DEUNA payment method type. | wallet |
processor_name | PayPal Wallet payment method identifier. | paypal_wallet |
Request
{
"token": "{{order-token}}",
"method_type": "wallet", // required for PayPal Wallet
"processor_name": "paypal_wallet", // required for PayPal Wallet
"email": "[email protected]",
"device_id": "xxxxxxx", // PayPal device ID, used in STC
"specific_fields": {
"callbacks": {
"on_success": "https://example.com" // required for PayPal Wallet
}
}
}
- Make a V2 Purchase
V2 purchases allow you to not have to create an order in DEUNA in a previous step.
This endpoint is in charge of creating an order and processing the payment in DEUNA if anorder token
is not passed to it and anorder object
is sent to it with all the required information.
Here is a list of required fields for PayPal Wallet:
Field | Description | Value |
---|---|---|
order.callback_urls.on_success | Redirect URL after authorizing the purchase with your PayPal Wallet account. | https://example.com/ |
payment_source.method_type | DEUNA payment method type. | wallet |
payment_source.processor | PayPal Wallet payment method identifier. | paypal_wallet |
Request
{
"order_type": "DEUNA_CHECKOUT",
"order_token": "{{order-token}}",
"order": {
"callback_urls": {
"on_success": "https://example.com" // required for PayPal Wallet
}
},
"payer_info": {
"email": "[email protected]"
},
"payment_source": {
"method_type": "wallet", // required for PayPal Wallet
"processor": "paypal_wallet" // required for PayPal Wallet
},
"anti_fraud_info": {
"device": {
"id": "xxxxxxx" // PayPal device ID, used in STC
}
}
}
Response
{
"order": {
"order_id": "620bbbf4-1f08-4cda-8609-dade541cb80e",
"store_code": "all",
"currency": "MXN",
"tax_amount": 0,
"display_tax_amount": "",
"shipping_amount": 0,
"display_shipping_amount": "MXN 0.00",
"items_total_amount": 2175,
"display_items_total_amount": "MXN 21.75",
"sub_total": 2075,
"display_sub_total": "MXN 20.75",
"total_amount": 2190,
"display_total_amount": "MXN 21.90",
"items": [
{
"id": "849fd015-2e1b-4ccc-a00c-aacbefeb71c8",
"name": "Papas",
"description": "Papas fritas con paprica",
"options": "",
"total_amount": {
"amount": 2100,
"original_amount": 2100,
"display_amount": "MXN 21.00",
"display_original_amount": "MXN 21.00",
"currency": "MXN",
"currency_symbol": "$",
"total_discount": 100,
"display_total_discount": "MXN 1.00"
},
"unit_price": {
"amount": 1050,
"display_amount": "MXN 10.50",
"currency": "MXN",
"currency_symbol": "$"
},
"tax_amount": {
"amount": 50,
"display_amount": "MXN 0.50",
"currency": "MXN",
"currency_symbol": "$"
},
"quantity": 2,
"uom": "",
"upc": "",
"sku": "",
"isbn": "",
"brand": "",
"manufacturer": "",
"category": "",
"color": "",
"size": "",
"weight": {
"weight": 0,
"unit": ""
},
"image_url": "https://media-cdn.tripadvisor.com/media/photo-s/1a/e2/c6/68/porcion-de-papas-a-la.jpg",
"details_url": "",
"type": "",
"taxable": true,
"discounts": [],
"included_in_subscription": false,
"item_details": []
},
{
"id": "c871341d-317b-4fdb-9d72-b55e55958633",
"name": "Refresco",
"description": "Coca-cola Sprite",
"options": "",
"total_amount": {
"amount": 90,
"original_amount": 75,
"display_amount": "MXN 0.90",
"display_original_amount": "MXN 0.75",
"currency": "MXN",
"currency_symbol": "$",
"total_discount": 0,
"display_total_discount": "MXN 0.00"
},
"unit_price": {
"amount": 75,
"display_amount": "MXN 0.75",
"currency": "MXN",
"currency_symbol": "$"
},
"tax_amount": {
"amount": 15,
"display_amount": "MXN 0.15",
"currency": "MXN",
"currency_symbol": "$"
},
"quantity": 1,
"uom": "",
"upc": "",
"sku": "",
"isbn": "",
"brand": "",
"manufacturer": "",
"category": "",
"color": "",
"size": "",
"weight": {
"weight": 0,
"unit": ""
},
"image_url": "https://media-cdn.tripadvisor.com/media/photo-s/1a/e2/c6/68/porcion-de-papas-a-la.jpg",
"details_url": "",
"type": "",
"taxable": true,
"discounts": [],
"included_in_subscription": false,
"item_details": []
}
],
"discounts": [],
"shipping_address": {
"id": 762,
"user_id": "",
"first_name": "Pablo",
"last_name": "Murillo",
"phone": "+551146733466",
"identity_document": "",
"lat": -22.943934,
"lng": -43.182984,
"address1": "Jose luis lagrange 3, 12",
"address2": "Polanco I Sección",
"city": "MIGUEL HIDALGO",
"zipcode": "11510",
"state_name": "CIUDAD DE MÉXICO",
"country_code": "MX",
"additional_description": "confirmar",
"address_type": "home",
"is_default": false,
"created_at": "2025-02-26T21:38:07Z",
"updated_at": "2025-02-26T21:38:07Z",
"identity_document_type": "",
"email": "[email protected]",
"state_code": "",
"country": "MX"
},
"shipping_options": null,
"user_instructions": "",
"metadata": {
"cd_string_one": 1,
"highrisk_txn_flag": 1,
"vertical": "Retail"
},
"status": "pending",
"payment": {
"data": {
"amount": {
"amount": 2190,
"currency": "MXN"
},
"metadata": {
"authorization_code": "",
"external_transaction_id": "6L9248503S6803027"
},
"from_card": {
"card_brand": "",
"first_six": "",
"last_four": "",
"bank_name": "",
"country_iso": "",
"credential_source": "",
"expiry_month": "",
"expiry_year": ""
},
"updated_at": "2025-02-26 21:38:12.748800962 +0000 UTC",
"method_type": "wallet",
"merchant": {
"store_code": "all",
"id": "2a18bdc9-d617-45cc-b718-838451dcf33a",
"affiliation_code": "",
"mcc": ""
},
"created_at": "2025-02-26 21:38:12.747998969 +0000 UTC",
"id": "620bbbf4-1f08-4cda-8609-dade541cb80e",
"processor": "paypal_wallet",
"customer": {
"email": "[email protected]",
"id": "9d920735-c3b1-4908-aba2-762d86fda7e0",
"first_name": "",
"last_name": ""
},
"status": "pending",
"reason": "",
"external_transaction_id": "6L9248503S6803027",
"merchant_payment_processor_name": "",
"authorization_code": "",
"installment_interest_calculations": null,
"next_action": {
"action": "authorization_wallet",
"url": "",
"authorization_wallet": {
"token": "6L9248503S6803027",
"redirect_url": "https://www.sandbox.paypal.com/checkoutnow?token=6L9248503S6803027"
}
},
"merchant_payment_processor_id": ""
}
},
"gift_card": [],
"redirect_url": "",
"webhook_urls": null,
"total_discount": 0,
"display_total_discount": "MXN 0.00",
"shipping": null,
"cash_change": 0,
"shipping_method": null,
"shipping_methods": [],
"timezone": "",
"scheduled_at": "",
"billing_address": {
"id": 191,
"user_id": "",
"first_name": "Pablo",
"last_name": "Murillo",
"phone": "+551146733466",
"identity_document": "",
"lat": -22.943934,
"lng": -43.182984,
"address1": "Jose luis lagrange 3, 12",
"address2": "Polanco I Sección",
"city": "MIGUEL HIDALGO",
"zipcode": "11510",
"state_name": "CIUDAD DE MÉXICO",
"country_code": "MX",
"additional_description": "confirmar",
"address_type": "home",
"is_default": false,
"created_at": "2025-02-26T21:38:07Z",
"updated_at": "2025-02-26T21:38:07Z",
"email": "[email protected]",
"identity_document_type": "",
"country": ""
},
"payment_link": "",
"display_shipping_tax_amount": "MXN 0.00",
"display_total_tax_amount": "MXN 1.15",
"shipping_tax_amount": 0,
"total_tax_amount": 115,
"user_id": "",
"include_payment_options": [],
"redirect_urls": {
"success": "",
"pending": "",
"error": "",
"fallback": "",
"close": ""
},
"created_at": "",
"updated_at": "",
"payer_info": null,
"discount_amount": 100,
"shipping_discount_amount": 0,
"device_fingerprint": "",
"expired_at": "",
"version": "0",
"fraud": {
"analysis": {
"score": 0.113950945,
"processor": "SIFT",
"risk_level": "",
"status": "automatic_decision",
"type": "",
"fraud_decision": "",
"details": "",
"processor_response": ""
}
},
"display_total_interest_amount": "",
"payment_method": "",
"token": "",
"statement_descriptor": "",
"browser_details": {
"screen_height": 1000,
"screen_width": 2000,
"user_agent": "",
"ip_address": "",
"color_depth": 0,
"java_enabled": false,
"java_script_enabled": false,
"language": "",
"time_zone_offset": 0,
"accept_header": ""
},
"callback_urls": null
},
"custom_fields": []
}
2. Redirect to PayPal
The purchase API returns a response with a pending
status and a next_action
containing the PayPal checkout URL, to redirect the user.
{
"order": {
"order_id": "620bbbf4-1f08-4cda-8609-dade541cb80e",
"store_code": "all",
"currency": "MXN",
"tax_amount": 0,
"display_tax_amount": "",
"shipping_amount": 0,
"display_shipping_amount": "MXN 0.00",
"items_total_amount": 2175,
"display_items_total_amount": "MXN 21.75",
"sub_total": 2075,
"display_sub_total": "MXN 20.75",
"total_amount": 2190,
"display_total_amount": "MXN 21.90",
...
"status": "pending",
"payment": {
"data": {
"method_type": "wallet",
"processor": "paypal_wallet",
"status": "pending",
"external_transaction_id": "6L9248503S6803027",
"next_action": {
"action": "authorization_wallet",
"url": "",
"authorization_wallet": {
"token": "6L9248503S6803027",
"redirect_url": "https://www.sandbox.paypal.com/checkoutnow?token=6L9248503S6803027"
}
},
...
}
},
"created_at": "",
"updated_at": "",
...
},
"custom_fields": []
}
3. Check the order status (Polling).
Once you direct the user to PayPal, check the payment status while they authorize it with their account, polling until the status changes.
Now get an Order and check the payment.data.status
.
Expected statuses
pending
The user has not yet authorized the payment on PayPal.processed
: The user authorized the payment on PayPal, and the capture was successful.denied
: An error occurred while processing the payment.
Response
{
"token": "ce7f91cc-7306-4a36-b9a8-b266545c56ba",
"order_type": "DEUNA_CHECKOUT",
"order": {
"order_id": "620bbbf4-1f08-4cda-8609-dade541cb80e",
"store_code": "all",
"currency": "MXN",
"tax_amount": 0,
"display_tax_amount": "MXN 0.00",
"shipping_amount": 0,
"display_shipping_amount": "MXN 0.00",
"items_total_amount": 2175,
"display_items_total_amount": "MXN 21.75",
"sub_total": 2075,
"display_sub_total": "MXN 20.75",
"total_amount": 2190,
"display_total_amount": "MXN 21.90",
"discounts": [],
"status": "succeeded",
"payment": {
"data": {
"method_type": "wallet",
"processor": "paypal_wallet",
"status": "processed",
"external_transaction_id": "5S773340XV029382D"
}
},
"created_at": "2025-02-26 21:38:07.860816361 +0000 UTC",
"updated_at": "",
"callback_urls": null
},
"custom_fields": [],
"checkout_modules": [],
"refunds": []
}
With vaulting
Use it when tokenization of a PayPal account is required to complete the purchase.
Get Payment Methods Response
{
"data": [
{
"enabled": true,
"method_type": "wallet",
"processor_name": "paypal_wallet", // PayPal Wallet identifier
"exclude_cvv": false,
"stored_payment_methods": [
{
"payment_method": "adb1ef51-e073-49f5-ba3b-a7e42344fd15",
"account_identifier": "[email protected]"
}
],
"id": "58745b8e-7127-44ea-84ef-656b3ffc611b", // Payment method ID
"authorization": {
"required": true,
"flow": "consent"
}
}
]
}
At this point, the user should be given the option to add a new account or proceed with the purchase using a previously tokenized account.
Add a new PayPal account
Follow these steps to tokenize a new account:
- Create customer’s consent.: Create a PayPal authorization request for the user.
- Request
curl --location --request POST '{{base_url}}/merchants/orders/{{order_token}}/consent?payment_method_id={{payment_method_id}}' \ --header 'X-API-KEY: {{merchant_private_key}}' \ --header 'Content-Type: application/json' \ --header 'X-Request-Id: xxxxx' \ --header 'Authorization: Bearer {{user_token}}'
- Response
{ "id": "1625a32a-df4c-4d9b-aec1-4510b3625865", "type": "transaction.authentication.pending", "created": "1740608931", "data": { "order": { "order_token": "7e975d44-a061-4d70-af0f-673f6ee56445", "transaction_id": "51b38afd-150f-419a-b718-b583209160fe", "external_transaction_id": "" }, "consent": { "id": "6fe9a045-9a46-4b25-8b60-d5a9586494c5", "status": "pending", "expires_at": "2025-02-26T22:38:51Z", "authorization_id": "5KA20765HT8087515", "redirect_url": "https://www.sandbox.paypal.com/agreements/approve?approval_session_id=5KA20765HT8087515" }, "error": null } }
- Request
- Redirect to PayPal: The API returns the consent as
pending
and a PayPal URL where the user must enter their account details and authorize its use.{ "id": "1625a32a-df4c-4d9b-aec1-4510b3625865", "type": "transaction.authentication.pending", "created": "1740608931", "data": { "order": { "order_token": "7e975d44-a061-4d70-af0f-673f6ee56445", "transaction_id": "51b38afd-150f-419a-b718-b583209160fe", "external_transaction_id": "" }, "consent": { "id": "6fe9a045-9a46-4b25-8b60-d5a9586494c5", "status": "pending", "expires_at": "2025-02-26T22:38:51Z", "authorization_id": "5KA20765HT8087515", "redirect_url": "https://www.sandbox.paypal.com/agreements/approve?approval_session_id=5KA20765HT8087515" }, "error": null } }
- Get customer’s consent status (Polling): After the user is directed to PayPal, check the consent status while they authorize the use of their account, polling until the status changes.
- Request
curl --location '{{base_url}}/merchants/orders/{{order_token}}/consent' \ --header 'X-API-KEY: {{merchant_private_key}}' \ --header 'Content-Type: application/json' \ --header 'X-Request-Id: xxxxx' \ --header 'Authorization: {{user_token}}'
- Response
{ "id": "4d226ecf-cd9a-4cc0-a3cf-fa8b2d0efab7", "type": "transaction.authentication.updated", "created": "1740609613", "callback_url": "", "data": { "request_id": "62551ffd-6d67-46cb-a436-f1ec3aa56087", "order": { "order_token": "00000000-0000-0000-0000-000000000000", "transaction_id": "", "external_transaction_id": "" }, "consent": { "id": "61fd7eb8-8a42-43fc-89d1-ab5c5ccaa0b9", "status": "success", "expires_at": "0001-01-01T00:00:00Z", "authorization_id": "95778196PH100683G", "redirect_url": "" }, "error": null } }
Possible statuses:
pending
: The user has not yet authorized the use of their PayPal account.success
: The user authorized the use of their PayPal account, and the account was successfully tokenized.denied
: An error occurred while tokenizing the account, or the user did not authorize the use of their account.expired
: The user did not authorize the use of their account in time.
The account appears in thestored_payment_methods
response obeject once the user's consent is authorized.
{
"data": [
{
"enabled": true,
"method_type": "wallet",
"processor_name": "paypal_wallet", // PayPal Wallet identifier
"exclude_cvv": false,
"stored_payment_methods": [
{
"payment_method": "6fe9a045-9a46-4b25-8b60-d5a9586494c5", // data.consent.id
"account_identifier": "[email protected]"
}
],
"id": "58745b8e-7127-44ea-84ef-656b3ffc611b", // Payment method ID
"authorization": {
"required": true,
"flow": "consent"
}
}
]
}
Now you have a tokenized PayPal account, the token is required for the next steps.
This account token is the
payment_method
field from the list ofstored_payment_methods
in the response of Get Payment Methods, or it can also be thedata.consent.id
field from the API response of Create or Get Consent
- Installments (optional)
You have the option to check the available installments for the user's PayPal account with the following request:
curl --location '{{base_url}}/merchants/transactions/orders/{{order_token}}/installments?payment_method={{payment_method}}&method_type=wallet&payment_method_id={{payment_method_id}}' \
--header 'x-api-key: {{merchant_public_key}}'
Response
{
"installments": [
{
"installments": 3,
"installments_amount": 3333,
"display_installments_amount": "MXN 33.33",
"installment_rate": 0,
"display_installment_label": "3 de $33.33 sin interés",
"plan_option_id": "2e0cc595-40e6-4ecf-b43b-35d5c33f88b6",
"installment_total_amount": 10000,
"installment_tax": [],
"display_installment_total_amount": "MXN 100.00"
},
{
"installments": 6,
"installments_amount": 1666,
"display_installments_amount": "MXN 16.66",
"installment_rate": 0,
"display_installment_label": "6 de $16.66 sin interés",
"plan_option_id": "25c7ef41-ebe8-4197-bdb3-f8651c261ea8",
"installment_total_amount": 10000,
"installment_tax": [],
"display_installment_total_amount": "MXN 100.00"
}
]
}
- Perform the purchase:
Here is a list of required fields for PayPal Wallet:
Field | Description | Value |
---|---|---|
method_type | DEUNA payment method type. | wallet |
processor_name | PayPal Wallet payment method identifier. | paypal_wallet |
payment_method | PayPal account token. | 6fe9a045-9a46-4b25-8b60-d5a9586494c5 |
payment_method_id | PayPal Wallet payment method ID returned in the id field of the Get Payment Methods response. | 58745b8e-7127-44ea-84ef-656b3ffc611b |
- Request
{ "token": "{{order-token}}", "method_type": "wallet", // required for PayPal Wallet "processor_name": "paypal_wallet", // required for PayPal Wallet "email": "[email protected]", "payment_method": "{{payment_method}}", // required "payment_method_id": "{{payment_method_id}}", // required "device_id": "xxxxxxx", // PayPal device ID, used in STC "specific_fields": { "callbacks": { "on_success": "https://example.com" // required for PayPal Wallet } } }
V2 purchases allow you to not have to create an order in DEUNA in a previous step.
This endpoint is in charge of creating an order and processing the payment in DEUNA if an order token
is not passed to it and anorder object
is sent to it with all the required information.
Here is a list of required fields for PayPal Wallet:
Field | Description | Value |
---|---|---|
payment_source.method_type | DEUNA payment method type | wallet |
payment_source.processor | PayPal Wallet payment method identifier. | paypal_wallet |
payment_source.payment_method | PayPal account token. | 6fe9a045-9a46-4b25-8b60-d5a9586494c5 |
payment_source.payment_method_id | PayPal Wallet payment method ID returned in the id field of the Get Payment Methods response. | 58745b8e-7127-44ea-84ef-656b3ffc611b |
- Request
{ "order_type": "DEUNA_CHECKOUT", "order_token": "{{order-token}}", "payer_info": { "email": "[email protected]" }, "payment_source": { "method_type": "wallet", // required for PayPal Wallet "processor": "paypal_wallet", // required for PayPal Wallet "payment_method": "{{payment_method}}", // required "payment_method_id": "{{payment_method_id}}" // required }, "anti_fraud_info": { "device": { "id": "xxxxxxx" // PayPal device ID, used in STC } } }
Response
{
"order_type": "DEUNA_CHECKOUT",
"order_token": "c582917a-07d2-4f07-b107-fd535e5565cb",
"order": {
"order_id": "777e66e5-3326-4b04-ad0a-93be7f2028bb",
"store_code": "all",
"currency": "MXN",
"tax_amount": 0,
"display_tax_amount": "",
"shipping_amount": 0,
"display_shipping_amount": "MXN 0.00",
"items_total_amount": 2175,
"display_items_total_amount": "MXN 21.75",
"sub_total": 2075,
"display_sub_total": "MXN 20.75",
"total_amount": 2190,
"display_total_amount": "MXN 21.90",
...
"status": "succeeded",
"payment": {
"data": {
"method_type": "wallet",
"processor": "paypal_wallet",
"customer": {
"email": "[email protected]",
"id": "9d920735-c3b1-4908-aba2-762d86fda7e0",
"first_name": "",
"last_name": ""
},
"status": "processed",
"external_transaction_id": "0YF74805EM9345944",
...
}
},
...
"callback_urls": null
}
}
Expected statuses:
succeeded
: Payment completed successfully.denied
: An error occurred while processing the payment.
Updated about 4 hours ago