Make a Payment
This guide will show you how to develop a flow that enables your customers to make a payment and place their order.
Before proceeding, you should have implemented:
Retrieve Stored Payment Methods
If the customer is logged in, you can retrieve all stored payment methods and present them to the customer for selection.
Using /customer-accounts/{customer_account_uuid}/stored-payment-methods you can fetch all stored payment methods:
Request
| Attribute | Type | Example Value | Description |
|---|---|---|---|
Authorization HTTP header |
string | "Bearer {customer_account_token}" |
JWT Token of Customer Account |
{
"method": "get",
"url": "https://api-public-playground.menu.app/api/customer-accounts/{customer_account_uuid}/stored-payment-methods",
"headers": {
"X-Request-ID": "69da3547-204b-4093-a225-54e084c24215",
"Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
"Api-Version": 4.38.0,
"Content-Type": "application/json",
"Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FwaS1wdWJsaWMtcGxheWdyb3VuZC5tZW51LmFwcC9hcGkvY3VzdG9tZXJzL3JlZnJlc2giLCJpYXQiOjE2OTEzMzA4NjUsImV4cCI6MTY5MTM4Nzg4OCwibmJmIjoxNjkxMzg0Mjg4LCJqdGkiOiJvNjF6Z2pqaVF4NHpUdTRaIiwic2V0UmVmcmVzaFRUTCI6MjYyODAwMCwic3ViIjoiNTA5MDYzNyIsInBydiI6ImNjMzI5MjFhMTU0ODBhMTE3ZDliYmM3MmMwZTEyNTZhNjg1MjQ1OGIiLCJhcHBsaWNhdGlvbl9pZCI6MjAxNSwic2Vzc2lvbl9pZCI6MjY2MjF9.9kk79vbjxOfcJprxGYoEeb8GYL3N3-k4KI-JaTgEdoQ"
}
}
Response
{
"code": 200,
"data": {
"stored_payment_methods": [
{
"id": "85688223-b4ee-4c0f-8593-513c182ef7b1",
"properties": {
"card_type": "visa",
"masked_number": "901010******0004",
"expiration_date": "12/2024",
"last_four_digits": "0004"
},
"preselected": true,
"payment_method_id": "027b59de-97cb-48a0-9404-37f426659bad"
}
]
},
"status": "OK"
}
| Attribute | Type | Example Value | Description |
|---|---|---|---|
stored_payment_methods |
array[StoredPaymentMethods] | Array of Stored Payment Methods that belong to the customer account | |
stored_payment_methods.[i].id |
string | "85688223-b4ee-4c0f-8593-513c182ef7b1" |
ID of the stored payment method - will be used to initialize payment |
stored_payment_methods.[i].properties.card_type |
string | "visa" |
String ID for Card Type |
stored_payment_methods.[i].properties.masked_number |
string | "901010******0004" |
First 6 digits and last 4 digits of credit card number (PAN) - some payment processors may only return last 4 digits |
stored_payment_methods.[i].properties.expiration_date |
string | "12/2024" |
Month / Year in which credit card will expire |
stored_payment_methods.[i].properties.last_four_digits |
string | "0004" |
Last 4 digits of credit card number (PAN) |
stored_payment_methods.[i].preselected |
bool | true |
Defines which payment method should be pre-selected for the customer on checkout - based on last-touched (last-used) payment method for the customer |
stored_payment_methods.[i].payment_method_id |
string | "027b59de-97cb-48a0-9404-37f426659bad" |
UUID of a registered payment method |
Initialize Payment
In order to start the payment processor, you will need to initialize a payment. Initializing a payment initiates the payment with the payment processor.
The payment initialization will contain different details depending on what the next step is to complete the payment.
Make a call to /payment-processors/init-payment:
Stored Payment Method
Request
| Attribute | Type | Example Value | Description |
|---|---|---|---|
Authorization HTTP header |
string | "Bearer {customer_account_token}" |
JWT Token of Customer Account |
venue_id |
string | "a9d6d0c8-1689-4114-b1ec-6da9c33f0384" |
UUID of Venue at which you are placing your order / making your payment |
payment_info.stored_payment_method_id |
string | "85688223-b4ee-4c0f-8593-513c182ef7b1" |
UUID from Stored Payment Method - from /customer-accounts/{customer_account_uuid}/stored-payment-methods |
payment_info.amount |
int | 255 |
Payment amount (lowest unit) |
order_info |
Order object | Order object as you would send it to POST /orders - see Place order for Dine-in (QS) or Takeout for more information |
{
"method": "post",
"url": "https://api-public-playground.menu.app/api/payment-processors/init-payment",
"headers": {
"X-Request-ID": "69da3547-204b-4093-a225-54e084c24215",
"Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
"Api-Version": 4.38.0,
"Content-Type": "application/json",
"Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FwaS1wdWJsaWMtcGxheWdyb3VuZC5tZW51LmFwcC9hcGkvY3VzdG9tZXJzL3JlZnJlc2giLCJpYXQiOjE2OTEzMzA4NjUsImV4cCI6MTY5MTM4Nzg4OCwibmJmIjoxNjkxMzg0Mjg4LCJqdGkiOiJvNjF6Z2pqaVF4NHpUdTRaIiwic2V0UmVmcmVzaFRUTCI6MjYyODAwMCwic3ViIjoiNTA5MDYzNyIsInBydiI6ImNjMzI5MjFhMTU0ODBhMTE3ZDliYmM3MmMwZTEyNTZhNjg1MjQ1OGIiLCJhcHBsaWNhdGlvbl9pZCI6MjAxNSwic2Vzc2lvbl9pZCI6MjY2MjF9.9kk79vbjxOfcJprxGYoEeb8GYL3N3-k4KI-JaTgEdoQ"
},
"body": {
"venue_id": "a9d6d0c8-1689-4114-b1ec-6da9c33f0384",
"payment_info": {
"stored_payment_method_id": "85688223-b4ee-4c0f-8593-513c182ef7b1",
"amount": 255
},
"order_info": {
"customer_info": {
"first_name": "Jane",
"last_name": "Doe",
"email": "jane.doe@partech.com",
"phone_number": "+11234567"
},
"menu_items": {
"id": "13d45e04-3f23-11ed-936c-1a67b454859d",
"price_level_id": "f1c0305d-74d0-4f7e-ac4f-668985dd3bb3",
"quantity": 1,
"comment": ""
},
"order_type": {
"id": "88a3e856-82c1-40a3-8a5f-185ca4e059ce",
"pickup_asap": true,
"pickup_at": "2023-06-23 11:37:12"
},
"singular_point_id": "75b78787-e139-4db8-b126-970d00ed4868"
}
}
}
Response
{
"status": "OK",
"code": 200,
"data": {
"payment_processor_type_id": 8,
"payment_init_hash": "9aafdada6062d5882dfddd598dc6b65b",
"allows_webhooks": false,
"expires_in": 897,
"status_polling_interval": 5,
"additional_info": {
"approval_url": "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-9LC27022SP413823L",
"token": "EC-9LC27022SP413823L",
"payment_id": "PAYID-MSKYH2Q5KM808023H7955515",
"client_id": "Abznyi4zfZ61uuXrV4zNv3ZLDR1gQNBTKG_gpw5-fCheROpgxOwbBHsIyf6hWJ_vKgLl3taawqXShF_E"
}
}
}
| Attribute | Type | Example Value | Description |
|---|---|---|---|
payment_processor_type_id |
id | 2 |
Payment Processor identifier (See Payment Processors for more information) |
payment_init_hash |
string | "021224037b0e8916a8ff54f085297f82" |
Payment hash uniquely identifying the initiated transaction |
allows_webhooks |
bool | true |
Boolean flag identifying whether the payment processor supports webhook updates for payment status. If allows_webhooks is true, then expires_in and status_polling_interval are used for short polling. |
expires_in |
int | 899 |
Transaction validity time in seconds. This applies to all payment processors. |
status_polling_interval |
bool | 5 |
Recommended status poll interval in seconds |
additional_info |
object | additional_info object contains the URLs specific to some of the payment processors |
Guest Payment Flow
Request
| Attribute | Type | Example Value | Description |
|---|---|---|---|
venue_id |
string | "a9d6d0c8-1689-4114-b1ec-6da9c33f0384" |
UUID of Venue at which you are placing your order / making your payment |
payment_info.payment_method_id |
string | "85688223-b4ee-4c0f-8593-513c182ef7b1" |
Payment method UUID. When venue information is retrieved [via /api/venues/{venue_id}?view=withNestedEntities] the response contains which payment methods are supported by the Venue and uuid for those payment methods. |
payment_info.amount |
int | 255 |
Payment amount (lowest unit) |
order_info |
Order object | Order object as you would send it to POST /orders - see Place order for Dine-in (QS) or Takeout for more information |
{
"method": "post",
"url": "https://api-public-playground.menu.app/api/payment-processors/init-payment",
"headers": {
"X-Request-ID": "69da3547-204b-4093-a225-54e084c24215",
"Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
"Api-Version": 4.38.0,
"Content-Type": "application/json"
},
"body":{
"amount":1464,
"venue_id":"4f41e5ef-4339-4570-9b6b-a1816c2f2d9c",
"payment_info":{
"amount":1464,
"payment_method_id":2
},
"order_info":{
"singular_point_id":"03646f80-0190-4e28-b140-0ed031fda317",
"order_type":{
"id":1,
"properties":{
},
"pickup_asap":true,
"pickup_at":"2023-08-15 08:44:36"
},
"tip":{
"percentage":10
},
"menu_items":[
{
"id":"48120369-ae5e-407a-a02b-1f9df44d400e",
"price_level_id":"76efaa5d-b849-4549-9468-72b8131b904a",
"quantity":1,
"comment":""
}
],
"customer_info":{
"first_name":"Jane",
"last_name":"Doe",
"email":"jane.doe@partech.com",
"demographics":[
]
}
},
"additional_info":{
"css_url":"https://order.kauwelapoke.com/saferpay-en.css"
}
}
}
| Attribute | Type | Example Value | Description |
|---|---|---|---|
payment_processor_type_id |
id | 2 |
Payment Processor identifier (See Payment Processors for more information) |
payment_init_hash |
string | "021224037b0e8916a8ff54f085297f82" |
Payment hash uniquely identifying the initiated transaction |
allows_webhooks |
bool | true |
Boolean flag identifying whether the payment processor supports webhook updates for payment status |
expires_in |
int | 899 |
Transaction validity time in seconds |
status_polling_interval |
bool | 5 |
Recommended status poll interval in seconds |
additional_info |
object | additional_info object contains the URLs specific to some of the payment processors |
Response
{
"status": "OK",
"code": 200,
"data": {
"payment_processor_type_id": 2,
"payment_init_hash": "7de87938a8e0d3e506aef8d3e917a6fa",
"allows_webhooks": false,
"expires_in": 899,
"status_polling_interval": 5,
"additional_info": {
"token": "6rxxqnreznx6td2cw0l0vlqg9",
"approval_url": "https://test.saferpay.com/vt2/Api/Post/241265/17998427/6rxxqnreznx6td2cw0l0vlqg9",
"url": "https://test.saferpay.com/vt2/Api/Post/241265/17998427/6rxxqnreznx6td2cw0l0vlqg9"
}
}
}
| Attribute | Type | Example Value | Description |
|---|---|---|---|
payment_processor_type_id |
id | 2 |
Payment Processor identifier (See Payment Processors for more information) |
payment_init_hash |
string | "7de87938a8e0d3e506aef8d3e917a6fa" |
Payment hash uniquely identifying the initiated transaction |
allows_webhooks |
bool | true |
Boolean flag identifying whether the payment processor supports webhook updates for payment status. If allows_webhooks is true, then expires_in and status_polling_interval are used for short polling. |
expires_in |
int | 899 |
Transaction validity time in seconds. This applies to all payment processors. |
status_polling_interval |
bool | 5 |
Recommended status poll interval in seconds |
additional_info |
object | additional_info object contains the URLs specific to some of the payment processors |
|
additional_info.token |
string | "6rxxqnreznx6td2cw0l0vlqg9" |
Optional field that is specific to Saferpay payment processor |
additional_info.approval_url |
string | "https://test.saferpay.com/vt2..." |
Optional field that is specific to Saferpay payment processor. In this case, you can use either approval_url or url to embed the hosted form into an iFrame. |
additional_info.url |
string | "https://test.saferpay.com/vt2..." |
Optional field that is specific to Saferpay payment processor. In this case, you can use either url orapproval_url to embed the hosted form into an iFrame. |
actions |
object | actions object contains next available actions and the correspondent URLs. Differs between payment processors. For ParPay contains type, which is redirect, and url for redirection. |
Payment Processor Web-App
Once the customer initializes the payment, the next step can differ based on the payment method chosen.
Credit / debit cards
In the case of credit/debit cards, depending on the payment processor that works behind the scenes, the customer should either:
-
See an embedded iframe where card details need to be entered
- White label apps receive the URL for the from a
generate-tokensrequest in case of authenticated flow, or from aninit-paymentrequest in case of a guest flow - Once the iframe is displayed, the customer enters their payment details and submits the form to the payment processor. To fetch the status of the payment, a listener should be implemented to verify the payment status
- Payment processors: Saferpay, FAC, Powertranz, Computop, Paystack, Freedompay, CCV, PAR Pay
- White label apps receive the URL for the from a
-
See a custom form that has separate iframes for each input field that the customer needs to populate or generally an empty division HTML container for embedding the whole third-party form
- Upon initializing the payment via the
init-paymentor generating a token for storing payment cards viagenerate-tokensrequest, the related payment solution's SDK needs to be initialized - Once the form is displayed, the customer enters their payment details and submits the form to the payment processor. To fetch the status of the payment, you need to adapt the payment solution's recommended ways (through their SDK) for verifying the payment -- most of them have callbacks for successful/failed payments
- Payment processors: Adyen, Cybersource, Checkout, FirstData
- Upon initializing the payment via the
-
See a third-party form that is embedded in an empty division HTML container where card details need to be entered. Still, once a customer clicks on a third-party "Pay" / "Add" button, the customer is redirected to a third-party web application (triggered by third-party SDK) where a customer needs to complete the payment
- After the payment has been processed, the third-party web application redirects the customer back to a white-label web application. It is important to note that upon being redirected back, the white-label app would need to immediately send either the
ordercreate request orstored-payment-methodrequest (depending on the customer's action). PAR Ordering API is responsible for verifying the payment status - Our web application supports that behavior only for PayMaya payment processor
- After the payment has been processed, the third-party web application redirects the customer back to a white-label web application. It is important to note that upon being redirected back, the white-label app would need to immediately send either the
-
Immediately gets redirected to a third-party web application (triggered by the white-label app) where a customer needs to enter card information and complete the payment
- After the payment has been processed, the third-party web application redirects the customer back to a white-label web application. It is important to note that upon being redirected back, the white-label app would need to immediately send either the POST
orderrequest or POSTstored-payment-methodrequest (depending on the customer's action). PAR Ordering API is responsible for verifying the payment status - Our web application supports that behavior only for Transbank payment processor
- After the payment has been processed, the third-party web application redirects the customer back to a white-label web application. It is important to note that upon being redirected back, the white-label app would need to immediately send either the POST
If 3DS is enforced on our CMS Brand level / enabled on Venue level configurations and the payment processor supports it, additional 3DS authentication might be required. Read more in the 3DS Authentication section.
Gift cards
In the case of gift cards, the customer should see the custom-made form for entering the gift card number, and if required, a security code. - Currently implemented and tied to PAR Pay integration
Alternative payment methods
In the case of alternative payment methods, we differentiate three types of integrations that PAR Ordering supports:
- APMs that work with their own SDK or a gateway script
- Upon initializing the payment via the
init-paymentrequest and receiving unnecessary data, you would need to initialize the relevant SDK and the customer should see just a button (e.g. “Pay with PayPal”) which would open the payment solution’s dialog (wallet). - You should check out the relevant SDK and third-party documentation to see how to verify the payment status – most of them have callbacks for successful/failed payments
- Payment methods/gateways: PayPal, MercadoPago, ApplePay, GooglePay
- Upon initializing the payment via the
- APMs that are embedded in an iframe
- Upon initializing the payment via the
init-paymentrequest, you will receive the URL which should be embedded into an iframe. The customer might need to authenticate within the iframe, but that depends on the payment method/gateway - Once the iframe is displayed, the customer enters their payment details and submits the form to the payment processor. To fetch the status of the payment, a listener should be implemented to verify the payment status updates
- Payment methods/gateways: GCash, Paystack Bank, Paystack USSD, Paystack Transfer, Paystack VisaQR
- Upon initializing the payment via the
- APMs that require top-window redirection
- Upon initializing the payment via the
init-paymentrequest, the customer should be immediately redirected to the third-party company web application where the customer needs to complete the payment. After that, the customer is redirected back to the white-label application. It is important to note that upon being redirected back, the white-label app would need to immediately trigger the order creation by sending the POSTorderrequest. PAR Ordering API is responsible for verifying the payment status - Payment methods/gateways: iDEAL, “Pay With PayMaya”
- Upon initializing the payment via the
Where to find necessary initialization data
There are two main ways to get the necessary information before showing an iframe or initializing the third-party SDK:
- From the
generate-tokensresponse - From the
init-paymentresponse
For the authenticated customer, at the step of storing the payment card, you will call the generate-tokens endpoint.
The response can differ from one payment processor to another. It can be found either in tokens.actions[i].url or in tokens.additional_info.url. Here are a few different examples.
Generate tokens response examples
PAR Pay:{
"status": "OK",
"code": 200,
"data": {
"tokens": [
{
"payment_processor_id": 392,
"payment_processor_type_id": 32,
"token": "47f3aa74-7583-4d2e-9261-4af468243bd9",
"actions": [
{
"type": "redirect",
"url": "https://api-public-playground.menu.app/api/payment-processors/init_token?mt_application_id={app_id}&mt_payment_processor_id={pp_id}&tokenType=1&template=card&isPayment=0&successUrl=https%3A%2F%2Fapi-public-playground.menu.app%2Fapi%2Fpayment-processors%2Fsuccess%3Fmt_application_id%3D683&failUrl=https%3A%2F%2Fapi-public-playground.menu.app%2Fapi%2Fpayment-processors%2Ffail%3Fmt_application_id%3D683&sessionId=309200423254396777680000333032&iframeUrl=https%3A%2F%2Fuatps48.aurusepay.com%2Fstoreservices%2Fecom%2Fgetiframe%3Fa%3D036937EFf1e9b6fe33a826efb184f6ecb618ef26582c0e1230febc98c8b2c6e3313e5e58ea96b27ca545ba2eada315a4ca74e7f225a212befa057406daa000b5cd1285379b41d776b891e78d654148e45ce4bf1f026e72cc005b6d37f86b0651276b12feb182913a8290da91a9566a25272615f9dbe2b8f8a261063146241bfc11a8be7689baf937b78cad120644c0a3d584b306e786b4821841b0a93dcc69c42290f9662d86ab452e2e09e0c7d66c51ab5333ca915df03d8a991e90cb0be695fc40859d99db4a7d03d656a0d1307847fdfda4aa2ccde314b0caca7a29f7ab0695dd5e8321e58309b85840708ec2e1d90f7515c801b9e609c6395decb1044765e2937cb2dd4fefc978f537833f263eb90120d14de5763b1279b2f20407ccd11c369095428675e3fd8364c82798f99446036e21c4b48b62f04eabdbd2ae7e9668348edf4ef0102af87ab8d15e67060cfbd8bc0147fb68a535fee9c70f65bf2001e30735d0e0dc700cea4ca00c8a552714c949b4ad558033c6b22dfff9e4b64f4894a133a5"
}
]
},
]
}
}
Saferpay:
{
"status": "OK",
"code": 200,
"data": {
"tokens": [
{
"payment_processor_id": 109,
"payment_processor_type_id": 2,
"token": "ol2ukt07agaearjz2k75u82xp",
"additional_info": {
"url": "https://test.saferpay.com/vt2/api/register/card/241265/ol2ukt07agaearjz2k75u82xp"
}
}
]
}
}
For the guest customer, as well as for alternative payment methods, at the step of vaulting, you will call the init-payment endpoint. Remember that we do not store payment cards for guest customers, and we also don't store APMs. Thus, the generate-tokens endpoint is never needed.
The response can differ from one payment processor to another. It can be found either in actions[i].url or in additional_info.url. Here are a few different examples.
Init payment response examples
PAR Pay:{
"status": "OK",
"code": 200,
"data": {
"payment_processor_type_id": 32,
"payment_init_hash": "08a12c45ae3643fa1d1875fa9f2493b0",
"allows_webhooks": false,
"expires_in": 898,
"status_polling_interval": 5,
"additional_info": null,
"actions": [
{
"type": "redirect",
"url": "https://api-public-playground.menu.app/api/payment-processors/init_token?mt_application_id={app_id}&mt_payment_processor_id={pp_id}&tokenType=1&template=card&isPayment=1&successUrl=https%3A%2F%2Fapi-public-playground.menu.app%2Fapi%2Fpayment-processors%2Fsuccess%3Fmt_application_id%3D683%26mt_payment_init_hash%3D08a12c45ae3643fa1d1875fa9f2493b0&failUrl=https%3A%2F%2Fapi-playground.menu.app%2Fapi%2Fpayment-processors%2Ffail%3Fmt_application_id%3D683%26mt_payment_init_hash%3D08a12c45ae3643fa1d1875fa9f2493b0&sessionId=309200223254404540620000370295&iframeUrl=https%3A%2F%2Fuatps48.aurusepay.com%2Fstoreservices%2Fecom%2Fgetiframe%3Fa%3D0369733Ff1e9b6fe33a826efb184f6ecb618ef26582c0e1230febc98c8b2c6e3313e5e58ea96b27ca545ba2eada315a4ca74e7f259025e0b77baa8235b8857c6ff633ab9397fc0f256fbbe4b600bbd581fd7994140df0cdb847a7fe370d33f7870b94eafb182913a8290da91a9566a25272615f94e955adcc467a55d4d266e33f35df96789baf937b78cad120644c0a3d584b306e786b4821841b0a93dcc69c42290f9662d86ab452e2e09e0c7d66c51ab5333ca915df03d8a991e90cb0be695fc40859d99db4a7d03d656a0d1307847fdfda4aa2ccde314b0caca7a29f7ab0695dd5e8321e58309b85840708ec2e1d90f7515c801b9e609c6395decb1044765e2937cb2dd4fefc978f537833f263eb90120d14de5763b1279b2f20407ccd11c369095428675e3fd8364c82798f99446036e21c4b48b62f04eabdbd2ae7e9668348edf4ef0102af87ab8d15e67060cfbd8bc0147fb68a535fee9c70f65bf2001e30735d0e0dc700cea4ca00c8a552714c949b4ad558033c6b22dfff9e4b64f4894a133a5"
}
]
}
}
Saferpay:
{
"status": "OK",
"code": 200,
"data": {
"payment_processor_type_id": 2,
"payment_init_hash": "272b59b61af516b90cafa0cfd20b574e",
"allows_webhooks": false,
"expires_in": 899,
"status_polling_interval": 5,
"additional_info": {
"token": "93itiab7h54m83r1byqlk2cs8",
"approval_url": "https://test.saferpay.com/vt2/Api/Post/241265/17998427/93itiab7h54m83r1byqlk2cs8",
"url": "https://test.saferpay.com/vt2/Api/Post/241265/17998427/93itiab7h54m83r1byqlk2cs8"
}
}
}
Poll Payment Status
Some of the payment processors support webhook payment status updates. allows_webhooks flag sent during init-payment identifies whether this feature is supported.
Webhooks is a server-to-server communication mechanism that allows payment gateway to send the notifications directly to the server, thus avoiding the potential client app issues. The idea is that, upon receiving a "payment created" notification, server should be able to create an order related to that payment without waiting for a client app to send the actual order create request.
Mainly webhooks implementation in PAR Ordering app is intended to be additional/backup flow that will take over if regular (redirect) flow fails.
To fetch the payment status, GET /api/payment-processors/init-payment/{init-payment-hash}/status should be called
Request
| Attribute | Type | Example Value | Description |
|---|---|---|---|
hash |
string | "27ef05b0d82e2512026f8f3833d887fb" |
Request parameter - init transaction payment hash (received from init-payment call as payment_init_hash property) |
{
"method": "get",
"url": "https://api-public-playground.menu.app/api/payment-processors/init-payment/{hash}/status",
"headers": {
"X-Request-ID": "69da3547-204b-4093-a225-54e084c24215",
"Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
"Api-Version": 4.38.0,
"Content-Type": "application/json",
"Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FwaS1wdWJsaWMtcGxheWdyb3VuZC5tZW51LmFwcC9hcGkvY3VzdG9tZXJzL3JlZnJlc2giLCJpYXQiOjE2OTEzMzA4NjUsImV4cCI6MTY5MTM4Nzg4OCwibmJmIjoxNjkxMzg0Mjg4LCJqdGkiOiJvNjF6Z2pqaVF4NHpUdTRaIiwic2V0UmVmcmVzaFRUTCI6MjYyODAwMCwic3ViIjoiNTA5MDYzNyIsInBydiI6ImNjMzI5MjFhMTU0ODBhMTE3ZDliYmM3MmMwZTEyNTZhNjg1MjQ1OGIiLCJhcHBsaWNhdGlvbl9pZCI6MjAxNSwic2Vzc2lvbl9pZCI6MjY2MjF9.9kk79vbjxOfcJprxGYoEeb8GYL3N3-k4KI-JaTgEdoQ"
}
}
Response
{
"code": 200,
"data": {
"payment_initialization_status": {
"order_uuid": "239e7982-3f23-11ed-936c-1a67b454859d",
"order_flow_status": "Success",
"order_flow_trigger_type": 1
}
},
"status": "OK"
}
| Attribute | Type | Example Value | Description |
|---|---|---|---|
payment_initialization_status.order_uuid |
string | "2da170c9-874c-4398-9436-12221fa1a9d3" |
Created Order UUID |
payment_initialization_status.order_flow_status |
string | "Success" |
Current status for the transaction. Possible values: Pending → initial status, the order flow has still not been triggered. Processing → the order flow has been triggered, but the order creation is still in progress. Success → order flow triggered and order creation has been completed successfully. Failed → order flow triggered, but order creation failed. |
payment_initialization_status.order_flow_trigger_type |
int | 2 |
If order flow status is not Pending then this value determines how the order procssing was triggered: 1 → triggered by order create API request, 2 → triggered by a webhook, 3 → triggered manually by a CLI command |
3DS Authentication
The 3D Secure will be enabled when these conditions are met:
- The configuration for 3DS is set on the CMS
- Enforced on the Brand-level configurations
- or enabled on the Venue-level configurations
- The payment processor supports it
The PAR Pay integration doesn’t support 3DS authentication, however, some other PAR Ordering integrations, such as Adyen, Cybersource, etc. do support it.
The API endpoint for fetching the URL in order to show the 3DS dialog is called auth-payment. It should be called after the init-payment call, after the customer submits the card details. Body of the request, as well as the response, depends on the payment processor used.
POST /api/payment-processors/auth-payment
Request
{
"method": "post",
"url": "https://api-public-playground.menu.app/api/payment-processors/auth-payment",
"headers": {
"X-Request-ID": "69da3547-204b-4093-a225-54e084c24215",
"Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
"Api-Version": 4.38.0,
"Content-Type": "application/json",
"Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FwaS1wdWJsaWMtcGxheWdyb3VuZC5tZW51LmFwcC9hcGkvY3VzdG9tZXJzL3JlZnJlc2giLCJpYXQiOjE2OTEzMzA4NjUsImV4cCI6MTY5MTM4Nzg4OCwibmJmIjoxNjkxMzg0Mjg4LCJqdGkiOiJvNjF6Z2pqaVF4NHpUdTRaIiwic2V0UmVmcmVzaFRUTCI6MjYyODAwMCwic3ViIjoiNTA5MDYzNyIsInBydiI6ImNjMzI5MjFhMTU0ODBhMTE3ZDliYmM3MmMwZTEyNTZhNjg1MjQ1OGIiLCJhcHBsaWNhdGlvbl9pZCI6MjAxNSwic2Vzc2lvbl9pZCI6MjY2MjF9.9kk79vbjxOfcJprxGYoEeb8GYL3N3-k4KI-JaTgEdoQ"
},
"body": {
"payment_init_hash": "fe455eb0e472cc60f8e286abc2221d2e",
"auth_info": {
"action_result": "eyJkZXRhaWxzIjp7InRocmVlZHMyLmZpbmdlcnByaW50IjoiZXlKMGFISmxaVVJUUTI5dGNFbHVaQ0k2SWxraWZRPT0ifSwicGF5bWVudERhdGEiOiJBYjAyYjRjMCFCUUFCQWdDem9uNEtNU0FWc1hWRklpcWFFNm8wWmY1d0lUbWlCVXFPaTdRQWN4cjdiN0RkdkxCWUtsWGNiVGR5YUpuRHJQMmluTGdlQjgyRmk0R3lqNFV3eGRudUxGVUFKSm83TWo3YWJReDY3NEdkSSsvWkJ4eXVBTnN2dnliREl6OWFrYU5IRHJnUGxteE1TZzBnQm8rQm90cjJWUU00RjFzdmlwSDFaYnArd2gxdHRKWEJQbXlzb2J3bDJVZXM4YmZHcWZNWHd3ZzFHQ0lz..."
}
}
}
| Attribute | Type | Example Value | Description |
|---|---|---|---|
payment_init_hash |
string | "fe455eb0e472cc60f8e286abc2221d2e" |
Payment hash uniquely identifying the initiated transaction |
auth_info.action_result |
string | "eyJkZXRhaWxzIjp7InRocmVWc1..." |
The object received from Adyen SDK, that we then turn into string and encode it using Base64 btoa global DOM API function. Optional parameter used for Adyen payment processor. |
auth_info.transient_token |
string | "eyJkZXRhaWxzIjp7InRocmVWc1..." |
The string received from Cybersource SDK, encoded in Base64. Optional parameter used for Cybersource payment processor. |
Response
{
"status": "OK",
"code": 200,
"data": {
"payment_processor_type_id": 11,
"payment_processor_id": "5bab16ce-bb27-4e62-aff4-124266647eaf",
"payment_init_hash": "fe455eb0e472cc60f8e286abc2221d2e",
"additional_info": {
"approval_url": null,
"approval_action": "eyJwYXltZW50RGF0YSI6IkFiMDJiNGMwIUJRQUJBZ0JqTXpQRlVWN2x3Y2tTYUxWT3kzR0R0QWV2V3JhbkFUUWtSM0plXC95R0JNQzUwYWhRS2UxbkQ0a05PT3NSaVg2UlE2MFBmdktXNThTZ1UyclBwUk11U0FGVlVKQXNDN3l2K0pmK0wzMUdoSnk5cURuQ1UwbVNqVFNlNHZqczJcL1ZSQisrUHg1RnVwYjdaM1ZXOUFNTjJheDV5cUdKaW5DOVdXY2pLRzBmXC8ySDdCU1dKaSs5djZ1UVVHMGFpTHh2SmcxbzBlSTkxcUhwQ1l0b2VpeHRwN2o3T0dKRzNZeUd0XC9LUGpYaU1GZUNKcitsUFhzN08wdnVCTUY4ZlRja1BXVjVENUprZUp5ZGNrcHUzdW9Ud01YSUsraGxqUUxXOHVZdmhBTllyaWpPR2J3cm9GTEpcL0tkcVA1RUVhMlhUdWdRaDlNaUxDMDNBYXk0eXpJOWFid1pnbEFNT0VCN0FVUTZJd0Jkd2RWWHJ...",
"client_encryption_public_key": "10001|A3795C2E0A78E5FF639AB006428D5EC19166AF82C402828476442E44476AE3DB9BE22468C15D8744574080DE5697FB81FBC4A0E0AB27B3B33A2739F20B1A514C6DCCBA3414E36F8056D4E1C007B6BF9ED5579A47313BDB651A3A984864E927B3A5D47CDA068E6A5C3AD76FB88A4173BC57EE672D421B13B3434F2D4B03FC250AAD86D64121A1760C83289EE7097A4643E493333ADE8373E9FB36A24F156C4B42D404879BBD8896705E0E91CD4F8BEC0E02A3F38D6EE275B6440F40B40E88B3D1B3292ABB331F9CB10E11D5AC81977ADCD0C22B7ECF009D608C651CC1FD7D4AA114B2130C6E82272224248B29CE4529DE93E5D010BD3976557067FD48E090B653",
}
}
}
| Attribute | Type | Example Value | Description |
|---|---|---|---|
payment_processor_type_id |
int | 11 |
Payment Processor identifier (See Payment Processors for more information) |
payment_processor_id |
string | "5bab16ce-bb27-4e62-aff4-124266647eaf" |
Payment Processor UUID |
payment_init_hash |
string | "fe455eb0e472cc60f8e286abc2221d2e" |
Payment hash uniquely identifying the initiated transaction |
additional_info.approval_action |
string | "eyJwYXltZW50RGF0YSI6IkFiM..." |
Base64 encoded string that can to be decoded using atob global DOM API function and then parsed into object. The object is then passed to payment processor SDK for initializing 3DS dialog. |
additional_info.approval_url |
string or null | "eyJwYXltZW50RGF0YSI6IkFiM..." |
Base64 encoded string passed usually together with approval_action to payment processor SDK for initializing 3DS dialog. For Adyen payment processor, this field is not needed, but for Cybersrouce both approval_url and approval_action are passed to Cybersource SDK as raw as they are. |
additional_info.client_encryption_public_key |
string or null | "10001A3795C2E0A78E5FF639A..." |
Optional parameter, specific to Adyen payment processor |
additional_info.authentication_transaction_id |
string or null | "10001A3795C2E0A78E5FF639A..." |
Optional parameter, specific to Cybersource payment processor |
Place Order
The payment status listener and the webhook long polling are the two processes running in parallel. The order creation process depends on the process that gets the update first:
-
In case the payment status update is received on the frontend side from the iFrame form, the order creation should be called directly from the client application by calling
https://api-public-playground.menu.app/api/orders(See the Generic Order create template for more details, or read more in the Ordering section) -
In case the payment status update is received via webhooks, the order is created automatically by PAR Ordering Core and can be polled by the
payment_initialization_status.order_uuidvia
POST https://api-public-playground.menu.app/api/orders/{order_uuid}/poll
Request
| Attribute | Type | Example Value | Description |
|---|---|---|---|
order_uuid |
string | "27ef05b0d82e2512026f8f3833d887fb" |
Request parameter - order UUID |
{
"method": "post",
"url": "https://api-public-playground.menu.app/api/orders/{order_uuid}/poll",
"headers": {
"X-Request-ID": "69da3547-204b-4093-a225-54e084c24215",
"Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
"Api-Version": 4.38.0,
"Content-Type": "application/json",
"Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FwaS1wdWJsaWMtcGxheWdyb3VuZC5tZW51LmFwcC9hcGkvY3VzdG9tZXJzL3JlZnJlc2giLCJpYXQiOjE2OTEzMzA4NjUsImV4cCI6MTY5MTM4Nzg4OCwibmJmIjoxNjkxMzg0Mjg4LCJqdGkiOiJvNjF6Z2pqaVF4NHpUdTRaIiwic2V0UmVmcmVzaFRUTCI6MjYyODAwMCwic3ViIjoiNTA5MDYzNyIsInBydiI6ImNjMzI5MjFhMTU0ODBhMTE3ZDliYmM3MmMwZTEyNTZhNjg1MjQ1OGIiLCJhcHBsaWNhdGlvbl9pZCI6MjAxNSwic2Vzc2lvbl9pZCI6MjY2MjF9.9kk79vbjxOfcJprxGYoEeb8GYL3N3-k4KI-JaTgEdoQ"
}
}
Response
{
"code": 200,
"data": {
"order": {
"id": "a823c634-6300-4f43-b536-8f1a183d568c",
"tax": 842,
"tip": 0,
"code": "BQIXC",
"uuid": "a823c634-6300-4f43-b536-8f1a183d568c",
"total": 17692,
"status": "SendDelayed",
"send_at": "2023-07-28 12:51:34",
"subsidy": 0,
"discount": 0,
"ready_at": "string",
"subtotal": 17692,
"tip_rate": 0,
"venue_id": "b8baafab-3f22-11ed-936c-1a67b454859d",
"discounts": [
{}
],
"init_hash": "5e6af1f1d4106e5221b181864bedb149",
"pickup_at": "2023-07-28 12:52:44",
"tax_rates": {
"5": 842
},
"ticket_id": "4a70a67b-b8d1-44b2-9ce4-e2fa6225a8d0",
"created_at": "2023-07-28 12:50:44",
"order_type": 4,
"arriving_at": "2023-07-28 12:52:44",
"combo_meals": [
{
"tax": 124,
"name": "Acai Bowl Early Nene-nui Combo",
"image": {
"fullsize": "/storage/images/combo_item_images/2021-09-08/6fd364994648905d3a74b3f05c299b42.png",
"thumbnail_small": "/storage/images/combo_item_images/_thumbs280/2021-09-08/6fd364994648905d3a74b3f05c299b42.png",
"thumbnail_medium": "/storage/images/combo_item_images/_thumbs720/2021-09-08/6fd364994648905d3a74b3f05c299b42.png"
},
"items": [
{
"tax": 124,
"name": "Làpana Bowl ",
"type": "Food",
"image": {
"fullsize": "/storage/images/combo_item_images/2021-09-08/6fd364994648905d3a74b3f05c299b42.png",
"thumbnail_small": "/storage/images/combo_item_images/_thumbs280/2021-09-08/6fd364994648905d3a74b3f05c299b42.png",
"thumbnail_medium": "/storage/images/combo_item_images/_thumbs720/2021-09-08/6fd364994648905d3a74b3f05c299b42.png"
},
"total": 2599,
"pos_id": "string",
"comment": "test comment combo item 1",
"type_id": 3,
"discount": 0,
"quantity": 1,
"subtotal": 2599,
"tax_rate": 5,
"modifiers": [
{
"name": "Organic Wild Rice",
"price": 0,
"pos_id": "string",
"modifier_id": "2049c354-3f23-11ed-936c-1a67b454859d",
"translations": {
"name": "Arroz Salvaje Ecológico"
}
}
],
"combo_group": {
"name": "Combo group",
"pos_id": "\"\"",
"type_id": 1,
"translations": {
"name": "Combo group"
},
"combo_group_id": "c1d5cd5e-3f22-11ed-936c-1a67b454859d"
},
"price_level": {
"name": "string",
"price": 2599,
"pos_id": "string",
"translations": {
"name": "string"
},
"menu_item_price_level_id": "0ffb254c-3f23-11ed-936c-1a67b454859d"
},
"menu_item_id": "19a394da-3f23-11ed-936c-1a67b454859d",
"translations": {
"name": "Làpana Bowl "
},
"service_charge": 0,
"is_self_serving": true,
"unpaid_item_hash": "string"
}
],
"total": 2599,
"pos_id": "string",
"type_id": 1,
"discount": 0,
"quantity": 1,
"subtotal": 2599,
"tax_rates": {
"5": 124
},
"custom_name": "Acai Bowl Early Nene-nui Combo",
"translations": {
"name": "Combo Cuenco Nene-nui Temprano con Acai",
"custom_name": "WCombo Cuenco Nene-nui Temprano con Acai"
},
"combo_meal_id": "04abaf54-3f23-11ed-936c-1a67b454859d",
"service_charge": 0
}
],
"delivery_at": "2023-07-28 12:51:34",
"order_items": [
{
"tax": 95,
"name": "Làpana Bowl",
"type": "Food",
"image": {
"fullsize": "/storage/images/item_images/2021-09-08/233451fe2256b3acf14ee5288e1b7dd0.png",
"thumbnail_small": "/storage/images/item_images/_thumbs280/2021-09-08/233451fe2256b3acf14ee5288e1b7dd0.png",
"thumbnail_medium": "/storage/images/item_images/_thumbs720/2021-09-08/233451fe2256b3acf14ee5288e1b7dd0.png"
},
"total": 1999,
"pos_id": "string",
"comment": "test comment",
"type_id": 1,
"discount": 0,
"quantity": 1,
"subtotal": 1999,
"tax_rate": 5,
"modifiers": [
{
"name": "Organic Wild Rice",
"price": 0,
"pos_id": "string",
"modifier_id": "2049c354-3f23-11ed-936c-1a67b454859d",
"translations": {
"name": "Arroz Salvaje Ecológico"
}
}
],
"price_level": {
"name": "string",
"price": 0,
"pos_id": "string",
"translations": {
"name": "string"
},
"menu_item_price_level_id": "0ffb254c-3f23-11ed-936c-1a67b454859d"
},
"menu_item_id": "19a394da-3f23-11ed-936c-1a67b454859d",
"translations": {
"name": "Cuenco de lapana,"
},
"service_charge": 0,
"is_self_serving": true,
"unpaid_item_hash": "string"
}
],
"pickup_code": "string",
"delivery_fee": 0,
"discount_info": "string",
"external_code": "string",
"pos_ticket_id": "\"\"",
"tax_exemption": 0,
"payment_status": "Reserved",
"service_charge": 0,
"delivery_status": "string",
"pos_ticket_code": "\"\"",
"delivery_fee_tax": 0,
"minimum_surcharge": 0,
"calculation_method": "string",
"external_reference": "string",
"external_channel_id": "string",
"regret_cancel_until": "2023-07-28 12:51:34",
"service_charge_rate": 0,
"tax_rates_exemption": {
"5": 0
},
"minimal_order_amount": 0,
"customer_account_info": {
"id": "6735e303-50a1-4887-9b11-915a6919cc66",
"email": "john.doe@partech.com",
"state": 1,
"locale": "en",
"type_id": 2,
"brand_id": "ea3c2a24-6210-40b3-84ef-447ee9d471b9",
"last_name": "Doe",
"first_name": "John",
"phone_number": "+3811111111",
"discount_cards": [
{}
],
"reference_type": "CustomerAccount",
"optin_status_pn": 3,
"optin_status_sms": 3,
"optin_status_email": 3
},
"delivery_fee_tax_rate": 0,
"minimum_surcharge_tax": 0,
"order_additional_info": {},
"order_type_properties": {
"type_id": 4,
"pickup_at": "order pickup at time",
"pickup_asap": true,
"customer_phone_number": "+3811111111"
},
"fraud_detection_status": "string",
"service_charge_tax_rate": 0,
"additional_delivery_info": "string"
}
},
"status": "OK"
}
| Attribute | Type | Example Value | Description |
|---|---|---|---|
order.id |
string | "77711288-ce6c-4e13-9a51-e6482c06fd37" |
Order UUID |
order.tax |
int | 842 |
The amount of order tax |
order.tip |
int | 0 |
The amount of order tips |
order.code |
string | "BQIXC" |
Unique order id in PAR Ordering system, Management Center and CMS |
order.total |
int | 1870 |
The total order amount in cents |
order.status |
string | "SendDelayed" |
Order status (see Order Statuses for more information) |
order.send_at |
string | 2023-07-28 12:51:34 |
Time when the order is to be sent to the POS printer |
order.ready_at |
string | 2023-07-28 12:59:34 |
Estimated time when the order will be ready |


