# Dojo Developer Documentation > Dojo provides payment APIs and SDKs for businesses to accept online and in-person payments, manage transactions, and integrate with EPOS systems. This file contains all documentation content in a single document following the llmstxt.org standard. ## Online payments You can create powerful custom integrations with the [Dojo API](https://docs.dojo.tech/api), building around the central concept of the [payment intent](https://docs.dojo.tech/payments/manage-payments/payment-intent). Online payments and in-person [Pay at Counter](https://docs.dojo.tech/payments/accept-payments/in-person-payments/pay-at-counter/introduction) transactions are both covered under the Dojo API. Dojo has also designed some ready-made online payments solutions that can be used to speed up integration for online payments. [![](https://docs.dojo.tech/images/dojo-icons/Bill.svg) **Checkout page** Discover the Dojo Prebuilt Checkout.](checkout-page) [![](https://docs.dojo.tech/images/dojo-icons/Wallet.svg) **Components** Use our ready-made JavaScript components.](components) [![](https://docs.dojo.tech/images/dojo-icons/WifiHigh.svg) **Payment links** Accept payments from customers without needing a full website.](payment-links) [![](https://docs.dojo.tech/images/dojo-icons/Laptop.svg) **Virtual terminal** Securely process phone and mail orders using your computer or mobile device.](virtual-terminal) --- ## Accept payments >Everything you need to know to accept payments. > **Tip:** Using an AI coding assistant? > Point your AI agent to our [LLM-friendly documentation](https://docs.dojo.tech/development-resources/llm-friendly-docs) for faster integration with Dojo APIs. [![](https://docs.dojo.tech/images/dojo-icons/ShoppingBag.svg) **Checkout Page** A prebuilt payment page for accepting payments on your website.](accept-payments/online-payments/checkout-page) [![](https://docs.dojo.tech/images/dojo-icons/Link.svg) **Payment Links** Send link to your customers, and accept payments without a website.](accept-payments/online-payments/payment-links) [![](https://docs.dojo.tech/images/dojo-icons/Plugin.svg) **Plugins** Third-party integrations that don't require programming skills, such as Magento and OpenCart.](/plugins) [![](https://docs.dojo.tech/images/dojo-icons/Layout.svg) **Components** Our ready-made JavaScript components that you can combine with your own components.](accept-payments/online-payments/components) [![](https://docs.dojo.tech/images/dojo-icons/Table.svg) **Pay at Table** Pay at table to process a transaction without the customer leaving their seat.](/payments/pay-at-table/introduction) [![](https://docs.dojo.tech/images/dojo-icons/PaymentCard.svg) **Pay at Counter** Pay at counter by having customers come up to the stationary waiter to complete their transaction.](accept-payments/in-person-payments/pay-at-counter/introduction) [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Need a hand?** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) --- ## In-person payments When a customer pays **in person**, that usually means they're on the premises with the merchant. When someone has a sit-down meal at a café, they will likely pay for it either by coming up to the service counter, or by paying at a card terminal when a waiter brings it over to their table. The [Pay at Counter (PAC)](https://docs.dojo.tech/api#tag/Terminals) (under `https://api.dojo.tech/terminals`) and the [Pay at Table (PAT)](https://docs.dojo.tech/tables/api/) APIs are designed for payment use cases involving EPOS systems. Dojo card machines need to be integrated with the other parts of a merchant's EPOS system, like the order screen and the receipt printer. [![](https://docs.dojo.tech/images/dojo-icons/Bill.svg) **Pay at Counter** Take payments at an EPOS.](pay-at-counter/introduction) [![](https://docs.dojo.tech/images/dojo-icons/PaymentCard.svg) **Pay at Table** Take payments at a customer's table.](/payments/pay-at-table/introduction) --- ## Pay at Counter >Learn how to capture or refund payments on a terminal, create a terminal session or retrieve a terminal. [![](https://docs.dojo.tech/images/dojo-icons/Bank.svg) **Terminals** The first step in any terminals integration.](terminals) [![](https://docs.dojo.tech/images/dojo-icons/Coins.svg) **Capture a payment** Step-by-step guide to capture a payment on a terminal.](./terminals/step-by-step-guide) [![](https://docs.dojo.tech/images/dojo-icons/Calculator.svg) **Create a session** Create a terminal session to start accepting payments.](./terminals/create-session) [![](https://docs.dojo.tech/images/dojo-icons/Email.svg) **Retrieve a terminal** Retrieve a terminal and accept payments.](./terminals/get-terminal) [![](https://docs.dojo.tech/images/dojo-icons/PenNib.svg) **Verify signature** Verify customer signatures in verification-required payments.](./terminals/signature-verification) [![](https://docs.dojo.tech/images/dojo-icons/PaymentCards.svg) **Cancel session** Cancel a terminal session.](./terminals/cancel-session) [![](https://docs.dojo.tech/images/dojo-icons/Tick.svg) **Go-live checklist** Ensure your integration is ready for production.](./go-live-checklist-f2f) [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Need a hand?** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) --- ## Go-live checklist To ensure you have a smooth onboarding with face-to-face payments on your EPOS, Dojo has prepared a comprehensive testing checklist that you can follow before going live with your integration. Please note that we mandate that at least one method of refunding is achievable through your integration to our API. This can be achieved directly through the [Payment Intent](https://docs.dojo.tech/api#tag/Refunds/operation/Refunds_Create) to refund to the original card used for payment, or by [creating a terminal session](https://docs.dojo.tech/api/#tag/Terminal-sessions/operation/TerminalSession_Create) either matched to a Payment Intent, or unmatched. Configuration These tests relate to how your EPOS is setup to interact with the Dojo API, taking into account authorization flow, user experience, and versioning. | Scenario | Steps to Reproduce | Expected Outcome | |-------|-----|----| | Authorization | See where these details are configured. This might not need to be in the UI of the EPOS software itself, but it could be in a configuration file, a database elsewhere, or even in a back-office system that end-users log in to. Also, record who is expected to enter the Cloud credentials: yourself, an installer, or the merchant. | POS allows configuring different API Keys. The API Key should never be hard-coded. | | Incorrect authorization credentials | Input an invalid API Key (You can simply input an extra character in the API key) | The EPOS should display an error prompting the user to check that the API key is correct. | | Retrieve terminal(s) | EPOS must be able to check for available terminals, preferably using the GET [/terminals](https://docs.dojo.tech/api#tag/Terminals) endpoint, or at a bare minimum offer the ability to manually enter the required `TID`. | POS should be able to check for available terminals or enable you to configure preferred `TID`. This should never be hard-coded. | | API version | Note which version of the API you are testing| This data is to be provided during QA.| | POS version | For our records, we prefer to keep a note of the minimum version of your POS which is compatible with this API - this allows us to track historic versions which may be incompatible. If this isn't providable (such as in the instance where only one version of the POS exists) then this step can be omitted. | Data to be provided during QA completion. | Payment intents These tests concern the creation of and management of payment intents, as well as additional features like `itemLines` and Webhooks. | Scenario | Steps to Reproduce | Expected Outcome | |------------|------|---------------------------| | [Create] Payment intent (Auto) | Initiate a sale using capture mode `AUTO` | Payment intent created successfully with the capture mode set to `AUTO` | | [Create] Payment intent (Manual) [Optional] | Initiate a sale using `captureMode: Manual` | Payment intent created successfully with the capture mode set to `Manual` (Optional) | | [Retrieve] Payment intent | GET [/terminals](https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_Get) the final result/transaction details from the [Payment Intents](https://docs.dojo.tech/api#tag/Payment-intents)API after the terminal session has concluded. | The POS recognizes the status of the intent and records the sale on the POS | | [Change] Payment intent amount [Optional] | Using the payment intent from a successful pre-authorization, use the POST [/payment-intents/{paymentIntentId}/amount](https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_SetCustomAmount) endpoint - This is before any pre-authorization or terminal session has taken place | Payment intent amount successfully updated| | [Cancel] Payment intent [Optional] | Cancel a payment that has not yet been authorized by using DELETE [/payment-intents/{paymentIntentId}](https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_Delete) | Payment intent is successfully cancelled | | [List] All Payment intents [Optional] | List all payment intents by posting to POST [/payment-intents/search](https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_Search). | Retrieves a list of payment intents. Results are paginated. By default, the method returns up to 50 payment intents. | | Create Payment intent - MOTO (CNP) | Initiate a transaction with `cardHolderNotPresent` set to **true**. | The card machine should skip the Present Card screen and go directly into Key Card Number | | itemLines | Use item lines to define checkout/bill items, and modifiers where applicable | Item lines should be correctly displayed and if discounts are present, these discounts should correctly display as modifiers. | | Webhooks | Subscribe to Webhook events to be notified of specific events. | List of all events subscribed to by sending a GET request to Dojo's webhooks endpoints. | Refunds These tests concern the refunding of payments by directly invoking the Payment Intent, avoiding the need for a card to be re-presented. | Scenario | Steps to Reproduce | Expected Outcome | |------------|------|---------------------------| | Create a full refund | Initiate a refund of a previously completed Payment Intent by POSTing to the refunds endpoint. | A 200 response is returned containing a `refundId`. The POS should then call GET on the Payment Intent ID, parse the final result of the intent (`Refunded`), and display that the payment was refunded. | | Create a partial refund | Initiate a refund of a previously completed Payment Intent by POSTing to the refunds endpoint. Select an amount lower than the original Payment Intent value. | A 200 response is returned containing a `refundId`. The POS should then call GET on the Payment Intent ID, parse the final result of the intent (`Captured`), and display that the payment was partially refunded. | [Auto] Create Terminal Session - Sale These tests cover the sales flow of terminal sessions created using `CaptureMode: Auto`, meaning that the transaction will be completed immediately. We look to cover as many possible transaction outcomes, including less common but still crucial flows such as `Expired` and `Signature Verification`. | Scenario | Steps to reproduce | Expected outcome | |----------|-------|---------| | Create terminal session - Successful while inserting card | Complete a transaction by inserting a card and using PIN entry or by using a Virtual Machine with `TID` ending in **SIP0**. | Must display transaction status of `Captured`. | | Create terminal session - Successful with cashback | Complete a transaction with cashback amount specified. | Cashback should be applied to the amount displayed on the card machine and recorded by the POS. | | Create terminal session - Successful with gratuity | Complete a transaction with gratuity amount specified. | Gratuity amount should be recorded by the POS. | | Create terminal session - Successful with contactless | Complete a transaction by presenting card to contactless reader. | POS should display result of Captured. | | Create terminal session - Successful with signature | Initiate a transaction by using a Virtual Machine with `TID` ending in **SIP0**. | POS should provide user with a dialogue box specifying that signature verification is required, and give the user an option to either accept or reject the signature. Selecting the accept option should send a PUT [/terminal-sessions/{terminalSessionId}/signature](https://docs.dojo.tech/api/#tag/Terminals/operation/TerminalSession_Signature) request with `accepted: true` and lead to a successful payment. | | Create terminal session - Successful with signature after 80 seconds | Initiate a transaction by using a Virtual Machine with `TID` ending in **SIP0**. At the status `SignatureVerificationRequired`, do not send a decision for 80 seconds. The signature step should time out as accepted, allowing the sale to continue to a successful outcome. | POS should display result of `Captured` for an auto-capture sale. | | Create terminal session - Declined | Initiate a transaction by using a Virtual Machine with `TID` ending in **DIP0**. | POS should display status Declined. POS should re-use Payment Intent if transaction is re-attempted. | | Create terminal session - Unsuccessful with signature rejection | Initiate a transaction by using a Virtual Machine with `TID` ending in **SIP0**. | POS should provide user with a dialogue box specifying that signature verification is required, and give the user an option to either accept or reject the signature. Selecting the reject option should send a PUT [/terminal-sessions/{terminalSessionId}/signature](https://docs.dojo.tech/api/#tag/Terminals/operation/TerminalSession_Signature) request with `accepted: false` and lead to a declined payment. | | Create terminal session - Late signature rejection after 80 seconds | Initiate a transaction by using a Virtual Machine with `TID` ending in **SIP0**. At the status `SignatureVerificationRequired`, do not send a decision for 80 seconds so the signature step times out as accepted. Then attempt to reject it. | POS should still display the successful result that was already finalized after the timeout (`Captured` for an auto-capture sale). | | Create terminal session - Failure with busy terminal | Initiate a sale while PDQ is in menu.| POS should display that PDQ is not available. | | Create terminal session - Cancel transaction from PDQ | Initiate a sale and cancel by selecting the X at the top of the PDQ screen before the card has been presented. | POS should display a result of Canceled. | | Create terminal session - Cancel transaction from POS - Successful | Initiate a sale and cancel by sending a PUT [/terminals](https://docs.dojo.tech/api#tag/Terminal-sessions/operation/TerminalSession_Cancel) to the cancel endpoint before the card has been presented. | POS should confirm status via polling and display a result of Canceled. | | Create terminal session - Cancel transaction from POS - Unsuccessful | Initiate a sale and cancel by sending a PUT [/terminals](https://docs.dojo.tech/api#tag/Terminal-sessions/operation/TerminalSession_Cancel) to the cancel endpoint after the card has been presented. | POS should confirm status via polling and transaction flow should be unaffected. | | Create terminal session - Expired | Initiate a transaction by using a Virtual Machine with `TID` ending in **TIP0** to retrieve a final status of `Expired`. | POS should display a dialogue advising that the result of the transaction cannot be confirmed and provide an option to manually record the sale on the POS as successful or retry if unsuccessful. | | Terminal session - polling rate | POS should call GET on terminal session regularly (once per second) to receive `notificationEvents` and `TerminalSessionStatus` updates | Polling should occur regularly enough that status updates are captured and displayed appropriately. | | Terminal session - display notifications | Complete several transactions invoking successful results, cancelation requests and signature verification to ensure relevant statuses are recorded effectively. | Terminal should display relevant `notificationEvents` and `TerminalSessionStatus` messages to the user to confirm the current state of the card machine. | [Manual] Create Terminal Session - Preauth These tests cover the sales flow of terminal sessions created using `captureMode: Manual`, meaning that the transactions will be pre-authorized and then captured subsequently. We will also look to cover behaviours such as incrementing the pre-authorized amount to ensure that the user experience is consistent. | Scenario | Steps to Reproduce | Expected Outcome | |-----|-------|-------| |Create terminal session - Successful with inserting card | Create a payment intent with capture mode set to manual. Create a terminal session and successfully authorize the payment using Chip and Pin or device verification. | Must display transaction status of Authorized. | | Create terminal session - Successful with contactless | Create a payment intent with capture mode set to manual. Create a terminal session and successfully authorize the payment using device verification. | Must display transaction status of Authorized. | | Create terminal session - Successful with different card type | Create a Payment intent with capture mode set to manual. Create a terminal session and successfully authorise the payment using a different card type to that used previously. | Must display transaction status of Authorized. | | Create terminal session - Declined | Initiate a transaction by by using a Virtual machine with TID ending "DIP0". | POS should display status Declined. POS should re-use Payment Intent if transaction is re-attempted. | | Update intent - Successful with increasing amount | Using the payment intent from a successful pre authorisation, use the "change payment intent amount" endpoint to increase the pre-authorized amount. | POS should receive a response with “Authorized” and display this. | | Update intent - Unsuccessful amount change | Try to update a previously captured payment intent. | The POS would display the error returned from the Dojo API, such as **Invalid request for payment with id `pi_sandbox_EaaC8tw2fUKVVoSUt5JgJQ`. The status `Captured` does not allow this change.** | | Update intent - Failure with non-existing payment intent id | Try to update an intent which does not exist. | The POS would ideally protect the user from this use case ever happening. | | Update intent - Failure when updating amount to zero | Try to update an intent to an amount `0`. | The POS would ideally protect the user from this use case ever happening. The POS would error with amount must be higher than `0`. | [Auto] Create Terminal Session - Refund These tests cover the refund flow of terminal sessions created using `captureMode: Auto`, meaning that the refunds will be completed immediately. | Scenario | Steps to Reproduce | Expected Outcome | |-----|-------|-------| |Create terminal session [Unlinked Refund - Successful]| Initiate an unlinked refund which is then authorized successfully. | The POS should parse the status of `Captured` returned in the terminal-session object and display that the refund was successful. | |Create terminal session [Unlinked Refund - Declined]| Initiate an unlinked refund which fails to authorize. | The POS should display that the refund was declined. | |Create terminal session [Unlinked Refund - Expired]| Initiate an unlinked refund and remove the battery during the authorization, allowing the transaction to expire after several seconds, or by using a Virtual Machine ending in "TIP0" to retrieve a final status of `Expired`. | POS should display a dialogue advising that the result of the refund cannot be confirmed, Please check the card machine screen for the result and provide an option to manually record the refund on the POS as successful or retry if unsuccessful. | |Create terminal session [Unlinked Refund - Cancelled]| Initiate an unlinked refund and cancel by selecting the X at the top of the PDQ screen before the card has been presented. | POS should display a result of Canceled. | |Create terminal session [Unlinked Refund - Successful with signature accepted]| Initiate an unlinked refund by by using a Virtual machine with TID ending "SIS0". | POS should provide user with a dialogue box specifying that signature verification is required, and give the user an option to either accept or reject the signature. Selecting the accept option should send a PUT of `"accepted": true` to the signature endpoint and lead to a successful refund. | |Create terminal session [Unlinked Refund - Unsuccessful with signature rejected]| Initiate an unlinked refund by by using a Virtual machine with TID ending "SIS0". | POS should provide user with a dialogue box specifying that signature verification is required, and give the user an option to either accept or reject the signature. Selecting the Decline option should send a PUT of `"accepted": false` to the signature endpoint and lead to a declined payment. | |Create terminal session [Matched Refund - Successful]| Initiate a matched refund which is then authorized successfully. | The POS should call GET on the Payment Intent, retrieve the status of `Refunded` and confirm this to the user. | |Create terminal session [Matched Refund - Declined]| Initiate a matched refund which fails to authorize. | The POS should display that the refund was declined. | |Create terminal session [Matched Refund - Expired]| Initiate a transaction by by using a Virtual machine with TID ending "TIP0" to retrieve a final status of `Expired`. | POS should display a dialogue advising that the result of the refund cannot be confirmed, Please check the card machine screen for the result and provide an option to manually record the refund on the POS as successful or retry if unsuccessful. | |Create terminal session [Matched Refund - Cancelled]| Initiate a matched refund and cancel by selecting the X at the top of the PDQ screen before the card has been presented. | POS should display a result of Canceled. | |Create terminal session [Matched Refund - Successful with signature accepted]| Initiate a matched refund by by using a Virtual machine with TID ending "SIS0". | POS should provide user with a dialogue box specifying that signature verification is required, and give the user an option to either accept or reject the signature. Selecting the accept option should send a PUT of `"accepted": true` to the signature endpoint and lead to a successful refund. | |Create terminal session [Matched Refund - Unsuccessful with signature rejected]| Initiate an unlinked refund by by using a Virtual machine with TID ending "SIS0". | POS should provide user with a dialogue box specifying that signature verification is required, and give the user an option to either accept or reject the signature. Selecting the Decline option should send a PUT of `"accepted": false` to the signature endpoint and lead to a declined payment. | Error testing These tests ensure that the POS is able to handle errors which will be returned from our API, ensuring that a valid error message and call to action is always displayed to the user. | Error testing | Description / Steps | |--------------|---------------------| |HTTP status code 400 - Bad Request| Occurs in the instance that a bad request is provided - this should be addressed prior to release by resolving the bad request. | |HTTP status code 401 - Unauthorized| Occurs when an invalid API Key is submitted. It's important, particularly in customer-driven installations, to provide clear user error-messaging here to ask that the credentials submitted by checked. | |HTTP status code 404 - Not found (TID unavailable)| In the event that the terminal is unavailable (offline, or powered off), the POS should advise the user accordingly and ask that they check the device status. | |HTTP status code 422 - Unprocessable Entity| This can be tested by attempting to cancel a payment outside of the "Insert Card" screen. The POS should respond and carry on with the previous request, and ideally advise the user of why the error occurred (eg: Payment can only be cancelled during the "Initiated" phase). | --- ## Cancel session >Cancel a terminal session. It might be necessary to cancel a terminal session without payment. ## Path When you need to cancel a terminal session, you can use the endpoint: > See OpenAPI spec for PUT endpoint details: https://docs.dojo.tech/api/#tag/Terminals/operation/TerminalSession_Cancel Note that the API method for cancelling a terminal session is `PUT` rather than `DELETE`. The session itself is not deleted, and it can be called up using the [get terminal](https://docs.dojo.tech/payments/accept-payments/in-person-payments/pay-at-counter/terminals/get-terminal) operation for reference. > **Note:** If payment has been attempted or completed > on a terminal session, it will no longer be possible to cancel it. This includes failed payment attempts. In the successful cancel session response, the `status` of the session will change to `CancelRequested`. The status will first move to `CancelRequested`. Finally, `status` of the session will change to `Canceled`. ## Sample requests ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl --location --request PUT 'https://api.dojo.tech/terminal-sessions/ts_sandbox_65af01524a36e6a14356dbc0/cancel' \ --header 'version: 2024-02-05' \ --header 'software-house-id: softwareHouse1' \ --header 'reseller-id: reseller1' \ --header 'Accept: application/json' \ --header 'Authorization: Basic sk_sandbox_1WYDtq7yAdqhmQ7KEUAvPlCCRBYc9HTY9KOPJKZtfWkzsSISj1L8c4GG5l4pBB5Bj85hkJgTL9vmOmki5QnQfQ' ``` [![](https://docs.dojo.tech/images/dojo-icons/TerminalWindow.svg) **API reference** Learn about the API and integrate with API endpoints.](/api/#tag/Terminals) [![](https://docs.dojo.tech/images/dojo-icons/ArrowBendUpLeft.svg) **Introduction** Return to the introduction page.](../introduction) [![](https://docs.dojo.tech/images/dojo-icons/Compass.svg) **Step-by-step guide** See the new terminals endpoints in practice.](step-by-step-guide) [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Support** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) --- ## Create session >Create a new session on an available terminal. You can create a terminal session on any `Available` terminal. If, as part of your integration, you need to develop logic for finding out which terminals are available, use one of the GET [/terminals](https://docs.dojo.tech/payments/accept-payments/in-person-payments/pay-at-counter/terminals/get-terminal) endpoint. A [payment intent](https://docs.dojo.tech/payments/manage-payments/payment-intent) is automatically initiated on the terminal when you create a terminal session. ## Path > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api/#tag/Terminals/operation/TerminalSession_Create ## Session types There are three Terminal session types: * a `sale`, which is associated with a [payment intent](https://docs.dojo.tech/payments/manage-payments/payment-intent) and therefore requires a `paymentIntentId`. * a `matchedRefund`, which also requires a `paymentIntentId`. * an `unlinkedRefund`, which is a refund that has not yet been associated with a payment intent. For an `unlinkedRefund`, you will have to specify the `amount` (the `value` in minor units, and the `currencyCode`) when you post the request to create a terminal session. For a `matchedRefund`, you will have to specify the `paymentIntentId` as well. ### Matched refund A matched refund requires the card and the customer to be physically present on the premises. The request references a payment intent and uses a terminal to process a *negative transaction*, which is the movement of funds to the card from the merchant account. ### Unlinked refund An unlinked refund also requires the card and the customer to be physically present, but it contains **no reference to a payment intent**. An unlinked refund theoretically allows for any amount of money to be refunded to anyone. This is ideal for EPOS systems which do not store previous transaction data, where refunds are processed without reference to the original sale's `paymentIntentId`. > **Tip:** Use `Authorization: Basic ` on these requests. `Basic ` is a literal prefix in Dojo's auth scheme, so do **not** base64-encode `api_key:`. > Sandbox and production both use `https://api.dojo.tech`; the API key determines the environment. In sandbox, use your assigned `software-house-id` and `reseller-id` if you have them; otherwise use the literal values `softwareHouse1` and `reseller1`. Production integrations always use values assigned by Dojo. ## Sample requests ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl --location --request POST 'https://api.dojo.tech/terminal-sessions' \ --header 'version: 2024-02-05' \ --header 'software-house-id: softwareHouse1' \ --header 'reseller-id: reseller1' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'Authorization: Basic sk_sandbox_1WYDtq7yAdqhmQ7KEUAvPlCCRBYc9HTY9KOPJKZtfWkzsSISj1L8c4GG5l4pBB5Bj85hkJgTL9vmOmki5QnQfQ' \ --data-raw '{ "terminalId": "tm_65a7e8c0bee9b6390862337c", "details": { "sale": { "paymentIntentId": "pi_sandbox_81Q7HAZSGkWLKFx_DFEe9Q" }, "sessionType": "Sale" } }' ``` [![](https://docs.dojo.tech/images/dojo-icons/TerminalWindow.svg) **API reference** Learn about the API and integrate with API endpoints.](/api/#tag/Terminals) [![](https://docs.dojo.tech/images/dojo-icons/ArrowBendUpLeft.svg) **Introduction** Return to the introduction page.](../introduction) [![](https://docs.dojo.tech/images/dojo-icons/Compass.svg) **Step-by-step guide** See the new terminals endpoints in practice.](step-by-step-guide) [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Support** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) --- ## Get terminal >Get information about terminals and terminal sessions. ## All terminals > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/api/#tag/Terminals/operation/Terminals_ListTerminals **Summary:** Retrieve all terminals, or all terminals with a specified `statuses` value. Setting `statuses` to `Available`, for example, will return a list of all terminals that are currently ready to use. Because `statuses` is an optional request field, leaving it blank will return a list of _all_ terminals of all statuses. ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl --location --request GET 'https://api.dojo.tech/terminals?statuses=Available' \ --header 'version: 2024-02-05' \ --header 'software-house-id: softwareHouse1' \ --header 'reseller-id: reseller1' \ --header 'Accept: application/json' \ --header 'Authorization: Basic sk_sandbox_1WYDtq7yAdqhmQ7KEUAvPlCCRBYc9HTY9KOPJKZtfWkzsSISj1L8c4GG5l4pBB5Bj85hkJgTL9vmOmki5QnQfQ' ``` ## A specified terminal > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/api/#tag/Terminals/operation/Terminals_GetTerminal **Summary:** Retrieve a specified terminal using its `terminalId`. ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl --location --request GET 'https://api.dojo.tech/terminals/tm_sandbox_65aaa2a8637e6374ac2447c9' \ --header 'version: 2024-02-05' \ --header 'software-house-id: softwareHouse1' \ --header 'reseller-id: reseller1' \ --header 'Accept: application/json' \ --header 'Authorization: Basic sk_sandbox_1WYDtq7yAdqhmQ7KEUAvPlCCRBYc9HTY9KOPJKZtfWkzsSISj1L8c4GG5l4pBB5Bj85hkJgTL9vmOmki5QnQfQ' ``` ## A terminal session > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/api/#tag/Terminal-sessions/operation/TerminalSession_Get **Summary:** Retrieve a specified terminal session by searching for the `terminalSessionId` while using the `/terminal-sessions` endpoint. ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl --location --request GET 'https://api.dojo.tech/terminal-sessions/ts_sandbox_65aa64bf637e6374ac244115' \ --header 'version: 2024-02-05' \ --header 'software-house-id: softwareHouse1' \ --header 'reseller-id: reseller1' \ --header 'Accept: application/json' \ --header 'Authorization: Basic sk_sandbox_1WYDtq7yAdqhmQ7KEUAvPlCCRBYc9HTY9KOPJKZtfWkzsSISj1L8c4GG5l4pBB5Bj85hkJgTL9vmOmki5QnQfQ' ``` [![](https://docs.dojo.tech/images/dojo-icons/TerminalWindow.svg) **API reference** Learn about the API and integrate with API endpoints.](/api/#tag/Terminals) [![](https://docs.dojo.tech/images/dojo-icons/ArrowBendUpLeft.svg) **Introduction** Return to the introduction page.](../introduction) [![](https://docs.dojo.tech/images/dojo-icons/Compass.svg) **Step-by-step guide** See the new terminals endpoints in practice.](step-by-step-guide) [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Support** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) --- ## Pre-authorization Pre-authorization is like opening a digital tab. It allows you to provide a seamless experience without charging the customer multiple times. * **The Start**: You begin by authorizing a base amount (e.g., £10) to verify the card. * **The Build**: As the customer continues to order, you can "top up" or increment that authorization to match their real-time spending. * **The Finish**: When they’re ready to leave, you capture the final total to settle the funds in a single transaction. **Use Case**: This is the gold standard for hospitality environments like bars, restaurants, or hotels where the final bill isn't known upfront. It's also ideal for corporate events where the cardholder does not have to stay until the end to settle the tab. ## The Start ### Step 1: Create a payment intent First, ensure you have already created a [payment intent](https://docs.dojo.tech/payments/manage-payments/payment-intent). This intent stores important information like payment details, amount, and currency. Please see the documentation for more information on configuration options. The example below is the basic request: ```json { "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order 234", "description": "Demo payment intent", "captureMode": "Manual", "autoExpireAction": "Release", "autoExpireIn": "00.10:00:00" } ``` > **Tip:** For pre-authorization, the `captureMode` must be set to `Manual`. ### Step 2: Check which terminals are available > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/api#tag/Terminals/operation/Terminals_ListTerminals **Main page**: [Retrieve all terminals](https://docs.dojo.tech/payments/accept-payments/in-person-payments/pay-at-counter/terminals/get-terminal/#all-terminals) You can check which terminals are available by requesting a list of all terminals or by requesting a filtered list of `Available` terminals. ### Step 3: Create a terminal session > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api/#tag/Terminals/operation/TerminalSession_Create **Main page**: [Create session](https://docs.dojo.tech/payments/accept-payments/in-person-payments/pay-at-counter/terminals/create-session) In your request, you will need to specify the terminal [`sessionType`](https://docs.dojo.tech/payments/accept-payments/in-person-payments/pay-at-counter/terminals/create-session/#session-types) and the ID of the payment intent you have already created. ```json { "terminalId": "tm_sandbox_65c5fe8a104a1222b2d8b968", "details": { "sale": { "paymentIntentId": "pi_sandbox_81Q7HAZSGkWLKFx_DFEe9Q" }, "sessionType": "Sale" } } ``` > **Tip:** To allow for bills greater than £100, payment via Chip and PIN or device verification (e.g., a mobile wallet) is required. A session will end once the initial authorization is complete. ## The Build ### Increment the authorized amount > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_SetCustomAmount To update the pre-authorized amount, use the [Change a payment intent amount endpoint.](https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_SetCustomAmount) This can be used multiple times for the same pre-authorization before you capture the final amount. ```json { "amount": { "value": 5500, "currencyCode": "GBP" } } ``` ## The Finish ### Capturing a final amount > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api#tag/Captures To complete the transaction, specify the final amount you wish to capture. You can capture the full authorized amount or a lower amount. Any remaining balance will be returned to the cardholder immediately after capture. ```json { "amount": 2000 } ``` ### Response example If your capture request is successful, the response will return information about the capture. ```json { "message": "collect payment for the order 3443", "captureId": "cp_itIiJMEAvES3ynYF_Yhs2g" } ``` --- [![](https://docs.dojo.tech/images/dojo-icons/TerminalWindow.svg) **API reference** Learn about the API and integrate with API endpoints.](/api/#tag/Terminals) [![](https://docs.dojo.tech/images/dojo-icons/ArrowBendUpLeft.svg) **Introduction** Return to the introduction page.](../introduction) [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Support** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) --- ## Signature verification >Respond to signature verification requests and accept or decline payment. Although only a small number of transactions will require signature verification, to be able to correctly support signature verification an endpoint including logic to handle these requests has been included as part of the Dojo API. > **Tip:** You'll only need to complete this step when the terminal session status changes to `SignatureVerificationRequired`. > > > ## Step 1. Create a payment intent > > First, make sure you've already created a [payment intent](https://docs.dojo.tech/payments/manage-payments/payment-intent). Visit the payment intents > documentation for more information about configuration options. This is where important information like payment details, amount, and currency are stored. > > ## Step 2: Check which terminals are available > > GET [/terminals](https://docs.dojo.tech/api#tag/Terminals/operation/Terminals_ListTerminals) > > **Main page**: [Retrieve all terminals](https://docs.dojo.tech/payments/accept-payments/in-person-payments/pay-at-counter/terminals/get-terminal/#all-terminals) > > You can check which terminals are available by requesting a list of all terminals, or by requesting a filtered list of `Available` terminals. > > ## Step 3: Create a terminal session > > POST [/terminal-sessions](https://docs.dojo.tech/api/#tag/Terminals/operation/TerminalSession_Create) > > **Main page**: [Create session](https://docs.dojo.tech/payments/accept-payments/in-person-payments/pay-at-counter/terminals/create-session) > > Over the course of a single business day, a terminal > might be associated with hundreds of sessions. > > In your request, determine the terminal [`sessionType`](https://docs.dojo.tech/payments/accept-payments/in-person-payments/pay-at-counter/terminals/create-session/#session-types). Make sure you've already created your > payment intent before creating a terminal session. You will have to specify the `paymentIntentId` in the request for `Sale` and `MatchedRefund` sessions. > Dojo will initiate the payment intent automatically once you've linked them. > > A session will end once the payment is complete, or once the refund has been fully processed. > > ## Step 4: Respond to a signature verification request > > PUT [/terminal-sessions/{terminalSessionId}/signature](https://docs.dojo.tech/api/#tag/Terminals/operation/TerminalSession_Signature) > > **Main page**: [Signature verification](https://docs.dojo.tech/payments/accept-payments/in-person-payments/pay-at-counter/terminals/signature-verification) > > **Tip:** The operator has 80 seconds to respond after the terminal session enters `SignatureVerificationRequired`. > > If no signature decision is submitted within that window, Dojo finalizes the signature step as accepted and the payment continues through its normal successful flow. For example, an auto-capture sale proceeds to `Captured`, while a manual-capture sale proceeds to `Authorized` until you capture it later. Respond to a signature verification request with **true** (to accept it) or **false** (to decline it). If you accept signature verification and send a request with the `accepted` field set to `true`, you will receive a detailed response object including both a `customerReceipt` and a `merchantReceipt`. ## Step 5: Retrieve the original payment intent Now that the customer has completed the payment on the terminal and the terminal has reached a final state, retrieve the original payment intent to ensure that the payment is complete. > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/api/#tag/Payment-intents/operation/PaymentIntents_Get --- [![](https://docs.dojo.tech/images/dojo-icons/TerminalWindow.svg) **API reference** Learn about the API and integrate with API endpoints.](/api/#tag/Terminals) [![](https://docs.dojo.tech/images/dojo-icons/ArrowBendUpLeft.svg) **Introduction** Return to the introduction page.](../introduction) [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Support** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) ## Sample requests ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl --location --request PUT 'https://api.dojo.tech/terminal-sessions/ts_sandbox_65aa64bf637e6374ac244115/signature' \ --header 'version: 2024-02-05' \ --header 'software-house-id: softwareHouse1' \ --header 'reseller-id: reseller1' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'Authorization: Basic sk_sandbox_1WYDtq7yAdqhmQ7KEUAvPlCCRBYc9HTY9KOPJKZtfWkzsSISj1L8c4GG5l4pBB5Bj85hkJgTL9vmOmki5QnQfQ' \ --data-raw '{ "accepted": true }' ``` ## Test your integration You can use your Dojo payment device to test your signature verification integration: 1. Start a new transaction on your EPOS. 2. Insert your [test card](https://docs.dojo.tech/development-resources/testing) into the payment device, wrong way round (not chip first). 3. Wait until the terminal tells you to remove card, then swipe it, too. 4. If successful, the signature verification process will commence. [![](https://docs.dojo.tech/images/dojo-icons/TerminalWindow.svg) **API reference** Learn about the API and integrate with API endpoints.](//api/#tag/Terminals) [![](https://docs.dojo.tech/images/dojo-icons/ArrowBendUpLeft.svg) **Introduction** Return to the introduction page.](../introduction) [![](https://docs.dojo.tech/images/dojo-icons/Compass.svg) **Step-by-step guide** See the new terminals endpoints in practice.](step-by-step-guide) [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Support** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) --- ## Step-by-step guide >A quick example of a Terminals flow. For ease of use, the request samples here will be cURL. The response samples are JSON. The language you use for your own integration may differ, and throughout Dojo's documentation there are code samples in [PHP, cURL, Python](https://github.com/dojo-engineering/dojo-samples), and other common languages and formats. Depending upon the `sessionType` you choose, perform the following steps for a successful terminal session: ![Payment Intent Flow](https://docs.dojo.tech/images/session-type-sale.jpg) **Flow diagram: Terminal Session — Sale** ```mermaid sequenceDiagram actor U as User participant T as Dojo Terminal participant E as EPOS system participant B as dojo backend U->>E: Places an order E->>B: POST /payment-intents (Sends payment information) B-->>E: Payment intent object E->>B: GET /terminals?statuses=Available (Requests for available terminals) B-->>E: List of available terminals E->>B: POST /terminal-sessions (details: sale) B-->>E: Terminal session object with amount to capture E->>T: Displays amount to capture U->>T: Presents card T->>B: Processes payment loop Poll for notifications E->>B: GET /terminal-sessions/{terminalSessionId} B-->>E: Terminal session object with status end T->>B: Sends response with the payment result B-->>E: Sends response with the payment result T-->>U: Print device receipt E-->>U: Print order receipt E->>B: GET /payment-intents/{paymentIntentId} B-->>E: Payment intent object ``` ![Payment Intent Flow](https://docs.dojo.tech/images/session-type-matched-refund.jpg) **Flow diagram: Session Type Matched Refund** ```mermaid sequenceDiagram actor U as User participant T as Dojo Terminal participant E as EPOS system participant B as dojo backend U->>E: Requests for a refund against a previous transaction E->>B: POST /payment-intents (Sends payment information) B-->>E: Payment intent object E->>B: GET /terminals?statuses=Available (Requests for available terminals) B-->>E: List of available terminals E->>B: POST /terminal-sessions (details: matchedRefund) B-->>E: Terminal session object with amount to capture E->>T: Displays amount to capture U->>T: Presents card T->>B: Processes payment loop Poll for notifications E->>B: GET /terminal-sessions/{terminalSessionId} B-->>E: Terminal session object with status end T->>B: Sends response with the refund transaction result B-->>E: Sends response with the refund result T-->>U: Print device receipt E-->>U: Print order receipt E->>B: GET /payment-intents/{paymentIntentId} B-->>E: Payment intent object ``` ![Payment Intent Flow](https://docs.dojo.tech/images/session-type-unlinked-refund.jpg) **Flow diagram: Session Type Unlinked Refund** ```mermaid sequenceDiagram actor U as User participant T as Dojo Terminal participant E as EPOS system participant B as dojo backend U->>E: Requests refund for a custom amount E->>B: GET /terminals?statuses=Available (Requests for available terminals) B-->>E: List of available terminals E->>B: POST /terminal-sessions (details: unlinkedRefund) B-->>E: Terminal session object with amount to capture E->>T: Displays amount to capture U->>T: Presents card T->>B: Processes payment loop Poll for notifications E->>B: GET /terminal-sessions/{terminalSessionId} B-->>E: Terminal session object with status end T->>B: Sends response with the refund transaction result B-->>E: Sends response with the refund result T-->>U: Print device receipt E-->>U: Print order receipt E->>B: GET /payment-intents/{paymentIntentId} B-->>E: Payment intent object ``` > **Note:** An `unlinkedRefund` refund session type contains no reference to a payment intent and can allow any amount to be refunded directly from the EPOS systems. **LLM walkthrough: complete Pay at Counter happy path** Use this as the canonical PAC template when your POS or middleware owns the basket, takes a card-present payment on a Dojo terminal, and later needs to issue a refund. All Dojo REST calls in this walkthrough use: - `Authorization: Basic ` (literal `Basic ` prefix; do not base64-encode `api_key:`) - `version: 2026-02-27` - `Content-Type: application/json` - `https://api.dojo.tech` for both sandbox and production; the API key determines the environment - `software-house-id: softwareHouse1` and `reseller-id: reseller1` on terminal endpoints in sandbox; production integrations receive assigned values from Dojo **Minimal end-to-end example (bash + curl)** This sample auto-accepts a signature request for demonstration purposes. In production, replace that with the operator's actual decision. ```bash API_KEY="sk_sandbox_your_key" BASE_URL="https://api.dojo.tech" VERSION="2026-02-27" COMMON_HEADERS=(-H "Authorization: Basic $API_KEY" -H "version: $VERSION" -H "Content-Type: application/json" -H "Accept: application/json") TERMINAL_HEADERS=("${COMMON_HEADERS[@]}" -H "software-house-id: softwareHouse1" -H "reseller-id: reseller1") PAYMENT_INTENT_ID=$( curl -sS "$BASE_URL/payment-intents" "${COMMON_HEADERS[@]}" \ -d '{"amount":{"value":1000,"currencyCode":"GBP"},"reference":"Order-234","captureMode":"Auto"}' \ | jq -r '.id' ) TERMINAL_ID=$( curl -sS "$BASE_URL/terminals?statuses=Available" "${TERMINAL_HEADERS[@]}" \ | jq -r '.[0].id' ) SESSION_ID=$( curl -sS "$BASE_URL/terminal-sessions" "${TERMINAL_HEADERS[@]}" \ -d "{\"terminalId\":\"$TERMINAL_ID\",\"details\":{\"sessionType\":\"Sale\",\"sale\":{\"paymentIntentId\":\"$PAYMENT_INTENT_ID\"}}}" \ | jq -r '.id' ) while :; do SESSION=$(curl -sS "$BASE_URL/terminal-sessions/$SESSION_ID" "${TERMINAL_HEADERS[@]}") STATUS=$(jq -r '.status' <<<"$SESSION") case "$STATUS" in InitiateRequested|Initiated|CancelRequested) sleep 1 ;; SignatureVerificationRequired) curl -sS -X PUT "$BASE_URL/terminal-sessions/$SESSION_ID/signature" "${TERMINAL_HEADERS[@]}" \ -d '{"accepted":true}' >/dev/null sleep 1 ;; Authorized|Captured|SignatureVerificationAccepted|SignatureVerificationRejected|Canceled|Declined|Expired) break ;; *) echo "Unexpected terminal session status: $STATUS" >&2; break ;; esac done curl -sS "$BASE_URL/payment-intents/$PAYMENT_INTENT_ID" "${COMMON_HEADERS[@]}" | jq ``` **1. Create the payment intent** **POST** `/payment-intents` **Request body** ```json { "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order-234", "description": "Card terminal sale for table 12", "captureMode": "Auto" } ``` **Response body** ```json { "id": "pi_sandbox_G_FeegU8WESxtY_Nct8jqw", "captureMode": "Auto", "status": "Created", "paymentMethods": [ "Card" ], "amount": { "value": 1000, "currencyCode": "GBP" }, "totalAmount": { "value": 1000, "currencyCode": "GBP" }, "refundedAmount": 0, "createdAt": "2024-04-07T23:25:44.802258Z", "updatedAt": "2024-04-07T23:25:44.802258Z", "reference": "Order-234", "description": "Card terminal sale for table 12", "paymentLink": "https://pay.dojo.tech/checkout/pi_sandbox_G_FeegU8WESxtY_Nct8jqw", "paymentEvents": [], "terminalSessionHistory": [] } ``` **2. Create the terminal session** **POST** `/terminal-sessions` **Request body** ```json { "terminalId": "tm_sandbox_65c5fe8a104a1222b2d8b968", "details": { "sale": { "paymentIntentId": "pi_sandbox_G_FeegU8WESxtY_Nct8jqw" }, "sessionType": "Sale" } } ``` **Response body** ```json { "createdAt": "2024-02-15T00:48:10.756Z", "details": { "sale": { "paymentIntentId": "pi_sandbox_G_FeegU8WESxtY_Nct8jqw" }, "sessionType": "Sale" }, "expireAt": "2024-02-15T00:48:20.756Z", "id": "ts_sandbox_65cd5f4a57ba13ad7424acd0", "notificationEvents": [], "status": "InitiateRequested", "statusEvents": [ { "createdAt": "2024-02-15T00:48:10.756Z", "debugMessage": "", "status": "InitiateRequested" } ], "terminalId": "tm_sandbox_65c5fe8a104a1222b2d8b968", "updatedAt": "2024-02-15T00:48:10.756Z" } ``` **3. Poll the terminal session until it reaches a terminal state** **GET** `/terminal-sessions/ts_sandbox_65cd5f4a57ba13ad7424acd0` Repeat this lookup while `status` is still in flight (`InitiateRequested`, `Initiated`, or `CancelRequested`). For a sale flow, the next meaningful outcome will be one of: - `Captured` for an auto-capture sale - `Authorized` for a manual-capture sale that still needs a later capture request - `SignatureVerificationRequired` when you must call **PUT** `/terminal-sessions/{terminalSessionId}/signature` - `Canceled`, `Declined`, or `Expired` when the session cannot complete successfully `Refunded` and `Reversed` are payment-intent states, not terminal-session states. **Response body** ```json { "createdAt": "2024-02-15T00:48:10.756Z", "details": { "sale": { "paymentIntentId": "pi_sandbox_G_FeegU8WESxtY_Nct8jqw" }, "sessionType": "Sale" }, "expireAt": "2024-02-15T00:49:40.756Z", "id": "ts_sandbox_65cd5f4a57ba13ad7424acd0", "notificationEvents": [ { "createdAt": "2024-02-15T00:48:11.980Z", "notificationType": "PresentCard" }, { "createdAt": "2024-02-15T00:48:16.066Z", "notificationType": "PleaseWait" }, { "createdAt": "2024-02-15T00:48:16.176Z", "notificationType": "EnterPin" }, { "createdAt": "2024-02-15T00:48:18.354Z", "notificationType": "RemoveCard" } ], "status": "Captured", "statusEvents": [ { "createdAt": "2024-02-15T00:48:10.756Z", "debugMessage": "", "status": "InitiateRequested" }, { "createdAt": "2024-02-15T00:48:10.972Z", "debugMessage": "", "status": "Initiated" }, { "createdAt": "2024-02-15T00:48:19.448Z", "debugMessage": "", "status": "Captured" } ], "terminalId": "tm_sandbox_65c5fe8a104a1222b2d8b968", "updatedAt": "2024-02-15T00:48:19.448Z" } ``` **4. Handle the successful payment notification and fetch the final payment intent** Use the webhook as the asynchronous confirmation, then read the payment intent for the full card-present result. **Webhook payload** ```json { "id": "evt_pac_01HPC2KQY7P5LZ5Q2B4W0A1B2C", "event": "payment_intent.status_updated", "accountId": "acc_test", "createdAt": "2024-02-15T00:48:19.448Z", "data": { "paymentIntentId": "pi_sandbox_G_FeegU8WESxtY_Nct8jqw", "paymentStatus": "Captured", "captureMode": "Auto" } } ``` **GET** `/payment-intents/pi_sandbox_G_FeegU8WESxtY_Nct8jqw` **Response body** ```json { "id": "pi_sandbox_G_FeegU8WESxtY_Nct8jqw", "captureMode": "Auto", "status": "Captured", "paymentMethods": [ "Card" ], "amount": { "value": 1000, "currencyCode": "GBP" }, "totalAmount": { "value": 1000, "currencyCode": "GBP" }, "refundedAmount": 0, "reference": "Order-234", "description": "Card terminal sale for table 12", "paymentDetails": { "transactionId": "19e4535e-ef6e-48e2-90be-d2b313c1cefd", "transactionDateTime": "2024-07-25T08:49:20.973410318Z", "message": "DEPOSITED", "authCode": "123456", "card": { "cardNumber": "44565300****1096", "cardName": "test", "expiryDate": "2024-12-31", "cardType": "VISA", "entryMode": "Contactless", "verificationMethod": "Pin" } }, "paymentEvents": [ { "transactionId": "19e4535e-ef6e-48e2-90be-d2b313c1cefd", "transactionDateTime": "2024-07-25T08:49:20.973410318Z", "eventType": "Captured", "authCode": "123456", "cardNumber": "44565300****1096", "expiryDate": "2024-12-31", "cardType": "VISA", "cardholderName": "test", "paymentMethodId": "" } ] } ``` **5. Refund the payment later with the Payment Intents API** Use the stored `paymentIntentId` for server-side refunds when the customer is no longer present. **POST** `/payment-intents/pi_sandbox_G_FeegU8WESxtY_Nct8jqw/refunds` **Request body** ```json { "amount": 1000, "refundReason": "Demo refund", "notes": "Customer returned the order in store" } ``` **Response body** ```json { "message": "refund for the order 3443", "refundId": "rfnd_g8mCx87TykeQ6BOXqxZ9NQ" } ``` For a card-present refund on the terminal instead of a server-side API refund, create a `matchedRefund` terminal session and reuse the original `paymentIntentId`. ## Step 1. Create a payment intent First, make sure you've already created a [payment intent](https://docs.dojo.tech/payments/manage-payments/payment-intent). Visit the payment intents documentation for more information about configuration options. This is where important information like payment details, amount, and currency are stored. ## Step 2: Check which terminals are available > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/api#tag/Terminals/operation/Terminals_ListTerminals **Main page**: [Retrieve all terminals](https://docs.dojo.tech/payments/accept-payments/in-person-payments/pay-at-counter/terminals/get-terminal/#all-terminals) You can check which terminals are available by requesting a list of all terminals, or by requesting a filtered list of `Available` terminals. ## Step 3: Create a terminal session > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api/#tag/Terminals/operation/TerminalSession_Create **Main page**: [Create session](https://docs.dojo.tech/payments/accept-payments/in-person-payments/pay-at-counter/terminals/create-session) Over the course of a single business day, a terminal might be associated with hundreds of sessions. In your request, determine the terminal [`sessionType`](https://docs.dojo.tech/payments/accept-payments/in-person-payments/pay-at-counter/terminals/create-session/#session-types). Make sure you've already created your payment intent before creating a terminal session. You will have to specify the `paymentIntentId` in the request for `Sale` and `MatchedRefund` sessions. Dojo will initiate the payment intent automatically once you've linked them. A session will end once the payment is complete, or once the refund has been fully processed. ## (Optional) Step 4: Cancel a terminal session > See OpenAPI spec for PUT endpoint details: https://docs.dojo.tech/api/#tag/Terminals/operation/TerminalSession_Cancel ```curl curl --location --request PUT 'https://api.dojo.tech/master/terminal-sessions/ts_sandbox_65af01524a36e6a14356dbc0/cancel ``` **Main page**: [Cancel session](https://docs.dojo.tech/payments/accept-payments/in-person-payments/pay-at-counter/terminals/cancel-session) You can cancel a terminal session as long as no card has been presented, inserted or swiped. If payment has been attempted or completed on a terminal session, it will no longer be possible to cancel it. ## (Optional) Step 5: Respond to a signature verification request > See OpenAPI spec for PUT endpoint details: https://docs.dojo.tech/api/#tag/Terminals/operation/TerminalSession_Signature **Main page**: [Signature verification](https://docs.dojo.tech/payments/accept-payments/in-person-payments/pay-at-counter/terminals/signature-verification) > **Tip:** You'll only need to complete this step if the terminal session status changes to `SignatureVerificationRequired`. Respond to a signature verification request with **true** (to accept it) or **false** (to decline it). If you accept signature verification and send a request with the `accepted` field set to `true`, you will receive a detailed response object including both a `customerReceipt` and a `merchantReceipt`. ## Step 6: Retrieve the original payment intent Now that the customer has completed the payment on the terminal and the terminal has reached a final state, retrieve the original payment intent to ensure that the payment is complete. > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/api/#tag/Payment-intents/operation/PaymentIntents_Get --- [![](https://docs.dojo.tech/images/dojo-icons/TerminalWindow.svg) **API reference** Learn about the API and integrate with API endpoints.](/api/#tag/Terminals) [![](https://docs.dojo.tech/images/dojo-icons/ArrowBendUpLeft.svg) **Introduction** Return to the introduction page.](../introduction) [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Support** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) --- ## Terminals >Integrate with the Dojo API to use Terminals operations ## Introduction The [Terminals endpoints](https://docs.dojo.tech/api/#tag/Terminals) included in the [Dojo API](https://docs.dojo.tech/api) integrate ["Pay at Counter"](https://support.dojo.tech/hc/en-gb/articles/360020950520-Using-Pay-at-Counter) functions. Similar to payment intents, you can capture payments on a terminal in one of the following capture modes: - `Auto`: by default, payments on a terminal are captured automatically without delay. This is ideal for immediate transactions. - `Manual`: use this mode when you need to reserve an amount on the customer's payment method to capture later. This is ideal for hotels to authorize a terminal before a guest checks in. For a successful transaction on the terminal, note how the Payment Intents endpoints and Terminals endpoints progress through some combination of statuses listed in the following diagrams: These diagrams combine **payment-intent** states and **terminal-session** states. The current terminal-session status enum is `InitiateRequested`, `Initiated`, `Authorized`, `Captured`, `CancelRequested`, `Canceled`, `SignatureVerificationAccepted`, `SignatureVerificationRejected`, `SignatureVerificationRequired`, `Expired`, and `Declined`. Payment-intent states such as `Reversed` and `Refunded` appear here only to show what can happen **after** a successful terminal collection flow. They are not terminal-session statuses. ![Payment Intent Flow](https://docs.dojo.tech/images/terminals-auto.jpg) **Flow diagram: Terminals Auto** ```mermaid stateDiagram-v2 state "PaymentIntent: Created" as created state "PaymentIntent: Canceled" as pi_canceled state "TerminalSession: InitiateRequested" as init_req state "TerminalSession: CancelRequested" as cancel_req state "TerminalSession: Initiated" as initiated state "TerminalSession: Canceled" as ts_canceled state "TerminalSession: Expired" as expired state "TerminalSession: Declined" as declined state "TerminalSession: SignatureVerificationRequired" as sig_req state "TerminalSession: SignatureVerificationRejected" as sig_rej state "TerminalSession: SignatureVerificationAccepted" as sig_acc state "TerminalSession / PaymentIntent: Captured" as captured state "PaymentIntent: Reversed" as reversed state "PaymentIntent: Refunded" as refunded [*] --> created: POST /payment-intents created --> pi_canceled: DELETE /payment-intents/{paymentIntentId} created --> init_req: POST /terminal-sessions init_req --> cancel_req: PUT /terminal-sessions/{terminalSessionId}/cancel cancel_req --> ts_canceled init_req --> initiated initiated --> expired initiated --> declined initiated --> ts_canceled initiated --> sig_req: Customer enters card details sig_req --> sig_rej sig_req --> sig_acc: PUT /terminal-sessions/{terminalSessionId}/signature sig_acc --> captured: (automatically captured) captured --> reversed: POST /payment-intents/{paymentIntentId}/reversal captured --> refunded: POST /payment-intents/{paymentIntentId}/refunds ``` ![Payment Intent Flow](https://docs.dojo.tech/images/terminals-manual.jpg) **Flow diagram: Terminals Manual** ```mermaid stateDiagram-v2 state "PaymentIntent: Created" as created state "PaymentIntent: Canceled" as pi_canceled state "TerminalSession: InitiateRequested" as init_req state "TerminalSession: CancelRequested" as cancel_req state "TerminalSession: Initiated" as initiated state "TerminalSession: Canceled" as ts_canceled state "TerminalSession: Expired" as expired state "TerminalSession: Declined" as declined state "TerminalSession: SignatureVerificationRequired" as sig_req state "TerminalSession: SignatureVerificationRejected" as sig_rej state "TerminalSession: SignatureVerificationAccepted" as sig_acc state "TerminalSession / PaymentIntent: Authorized" as authorized state "TerminalSession / PaymentIntent: Captured" as captured state "PaymentIntent: Reversed" as reversed state "PaymentIntent: Refunded" as refunded [*] --> created: POST /payment-intents created --> pi_canceled: DELETE /payment-intents/{paymentIntentId} created --> init_req: POST /terminal-sessions init_req --> cancel_req: PUT /terminal-sessions/{terminalSessionId}/cancel cancel_req --> ts_canceled init_req --> initiated initiated --> expired initiated --> declined initiated --> ts_canceled initiated --> sig_req: Customer enters card details sig_req --> sig_rej sig_req --> sig_acc: PUT /terminal-sessions/{terminalSessionId}/signature sig_acc --> authorized authorized --> reversed: POST /payment-intents/{paymentIntentId}/reversal authorized --> captured: POST /payment-intents/{paymentIntentId}/captures captured --> refunded: POST /payment-intents/{paymentIntentId}/refunds ``` ### Create a terminal session > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api/#tag/Terminals/operation/TerminalSession_Create **Summary**: [Create a session on a terminal](https://docs.dojo.tech/plugins/woocommerce/terminals/create-session) to initiate an in-person payment. This endpoint allows you to establish a connection with the terminal and prepare it for processing payments. Creating a terminal session also automatically initiates whichever [payment intent](https://docs.dojo.tech/manage-payments/payment-intent) ID you specified in the request. ### Retrieve all terminals > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/api/#tag/Terminals/operation/Terminals_ListTerminals **Summary:** [Retrieve all terminals](https://docs.dojo.tech/plugins/woocommerce/terminals/get-terminal#all-terminals) associated with your account. This endpoint provides information about each terminal in an array. ### Retrieve a terminal > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/api/#tag/Terminals/operation/Terminals_GetTerminal **Summary:** [Retrieve a terminal](https://docs.dojo.tech/plugins/woocommerce/terminals/get-terminal#a-specified-terminal) by providing its `terminalId`. ### Retrieve a terminal session > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/api#tag/Terminal-sessions/operation/TerminalSession_Get **Summary:** [Retrieve a terminal session](https://docs.dojo.tech/plugins/woocommerce/terminals/get-terminal#a-terminal-session) by providing its `terminalSessionId`. ### Signature verification > See OpenAPI spec for PUT endpoint details: https://docs.dojo.tech/api/#tag/Terminals/operation/TerminalSession_Signature **Summary:** [Respond to a signature verification request](https://docs.dojo.tech/plugins/woocommerce/terminals/signature-verification). Useful for authorizing and finalizing the small number of modern transactions that still require a customer signature to confirm payment. ### Cancel a terminal session > See OpenAPI spec for PUT endpoint details: https://docs.dojo.tech/api/#tag/Terminals/operation/TerminalSession_Cancel **Summary**: [Cancel a terminal session](https://docs.dojo.tech/plugins/woocommerce/terminals/cancel-session), as long as no payment has been attempted or completed on it. > **Tip:** `tid` and `terminalId` are separate concepts. A `tid` is a unique industry-wide eight-digit ID that is assigned by the terminal manufacturer to troubleshoot hardware issues. A `terminalId` is a terminal identifier used by Dojo during the payment process. ## Expired state During a terminal session, the object may conclude in a status of `Expired`. This can occur in the event of complete disconnection between API and terminal during a transaction, and results in the **Dojo API** being unable to resolve the session, leading to a timed-out state. In the event of an `Expired` result, the POS should provide the user with clarification of the error, a prompt to check the result on the payment device screen or receipt, and with the ability to manually conclude the payment on the POS by either manually recording the payment as successful, or by re-initiating the terminal-session if the payment has failed. [![](https://docs.dojo.tech/images/dojo-icons/TerminalWindow.svg) **API reference** Learn about the API and integrate with API endpoints.](/api/#tag/Terminals) [![](https://docs.dojo.tech/images/dojo-icons/ArrowBendUpLeft.svg) **Introduction** Return to the introduction page.](introduction) [![](https://docs.dojo.tech/images/dojo-icons/Compass.svg) **Step-by-step guide** See the new terminals endpoints in practice.](./terminals/step-by-step-guide) [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Support** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) --- ## Tap to Pay Dojo offers SDKs for integrating contactless [NFC-enabled](https://support.google.com/wallet/answer/12200245) tap-to-pay functionality on both [iOS](https://www.apple.com/uk/newsroom/2023/07/apple-introduces-tap-to-pay-on-iphone-in-the-uk/) and [Android](https://pay.google.com/about/pay-in-store/) devices. For detailed information on each platform's SDK, including supported cards, countries, compatibility, and integration steps, please refer to the individual SDK pages linked below: - [Tap to Pay on iPhone SDK](https://docs.dojo.tech/tap-to-pay-on-iphone) - [Tap to Pay Android SDK](https://docs.dojo.tech/tap-to-pay-on-android) ## Connect with the community [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Support** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) [![](https://docs.dojo.tech/images/dojo-icons/Message.svg) **Stack Overflow** Find answers to practical questions.](https://stackoverflow.com/tags/dojo.tech) --- ## Tap to Pay on iPhone SDK > Accept contactless payments on your iPhone with Dojo's Tap to Pay on iPhone SDK. ## Overview Dojo's Tap to Pay on iPhone SDK lets you integrate payments in your app on the iPhone seamlessly. ## Supported cards and countries | Card supported | 🇬🇧 | |--------------------|---------| | VISA | ✅ | | Mastercard/Maestro | ✅ | | Discover | ❌ | | Diners Club | ❌ | | American Express | ✅ | ## Compatibility The **Tap to Pay on iPhone SDK** is compatible with: - iPhone XS or later with iOS 16.7 or later. ## Step-by-step guide Integrating the SDK is a 2-step process. 1. Activate device 2. Collect payment ![Activate device](https://docs.dojo.tech/images/tapple/activate-terminal.png) ![Collect payment](https://docs.dojo.tech/images/tapple/collect-payment.png) ## Activate device ### Prerequisites To build the SDK, ensure you have the following: - XCode Version **15.3 (15E204a)** or later. ### Setup In order to activate a terminal on a device, you'll need to integrate Dojo Tap to Pay on iPhone SDK into your app. The SDK is available using SPM. 1. Go to **File > Add Packages...** and in **Repository URL**, add `https://github.com/dojo-engineering/dojo-tap-to-pay-on-iphone-sdk`. 2. Enter the latest version number of the SDK, that is, `0.0.11`. 3. In the [target of your app](https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app), add **DojoTapToPayOniPhoneSDK**. 4. Click **Add package**. This installs the SDK. 5. Add the following entitlement to your app: [https://developer.apple.com/documentation/proximityreader/setting-up-the-entitlement-for-tap-to-pay-on-iphone](https://developer.apple.com/documentation/proximityreader/setting-up-the-entitlement-for-tap-to-pay-on-iphone) ```xml com.apple.developer.proximity-reader.payment.acceptance ``` ## Demo Check out our working [demo app](https://github.com/dojo-engineering/dojo-tap-to-pay-on-iphone-sdk/tree/main/SampleApp) to see an integration of the SDK. ### Configure your app > Learn how to configure your app using the Tap to Pay on iPhone SDK. After you have set up the SDK, you need to configure your app using the following steps: 1. Authenticate your backend by [generating an API key](https://docs.dojo.tech/payments/getting-started). 2. Generate a `secret` key using the POST [/secret](https://docs.dojo.tech/api#tag/Tap-to-Pay-on-iPhone/operation/CreateTerminalSecret) endpoint. ```bash curl --request POST \ --url https://staging-api.dojo.dev/integration-test/tap/apple-terminal/secret \ --header 'Authorization: Basic sk_sandbox_EtKXUrMCHU9Y7NCURtDRI9KEn0yqWDgy4JFUOeg0QNGRihcml31fxJURpfbdlx1D' \ --header 'Version: 2023-12-12' ``` 3. Pass this `secret` key when using the `DojoTapToPayOniPhoneSDK` in your app's `.swift` file. For example: `.activateTerminal(secret: )` > **Note:** During activation process, if your `secret` key expires, generate a new `secret` key and try again. 4. Start activation as follows and you'll be notified by the SDK once your device activation is complete. ```swift let dojoSDK = DojoTapToPayOniPhone(env: .staging) // use .staging or .production let secret: String = "" do { let initialStatus = try await dojoSDK.activateTerminal(secret) guard initialStatus != .operational { return } // proceed when the status is operational let terminalStatus = try await dojoSDK.getTerminalActivationStatus(notifyWhenOperational: true, secret: secret) print(terminalStatus) } catch { print(error) } ``` ### Notifications > **Note:** Using `getTerminalActivationStatus(notifyWhenOperational: Bool, secret: String)` with `notifyWhenOperational: true` will subscribe to and receive ongoing status updates until the SDK is operational. ## Take payments In order to start a payment, do the following: 1. Obtain a `secret` key (the same way as you did for activation flow) and a [payment intent](https://docs.dojo.tech/payments/accept-payments/online-payments/checkout-page/step-by-step-guide#step-1-create-a-payment-intent). 2. Check that your AppleID account is linked with the card reader before starting to take a payment. 3. Pass the `secret` key and `paymentIntentId` to the `DojoTapToPayOniPhoneSDK` object calling `.startPayment(paymentIntentId: String, secret: String)`. You'll be notified by the SDK once the transaction is completed. ```bash let dojoSDK: DojoTapToPayOniPhone = DojoTapToPayOniPhone(env: .staging) let secret: String = "" do { if try await dojoSDK.isAccountLinked(secret) == false { try await dojoSDK.linkAccount(secret) } } catch { print(error) } ``` ```bash let dojoSDK: DojoTapToPayOniPhone = DojoTapToPayOniPhone(env: .staging) let secret: String = "" let paymentIntentId: String = "" do { let terminalStatus = try await dojoSDK.getTerminalActivationStatus(secret: secret) if initialStatus != .operational { // restart activation return } let result = try await dojoSDK.startPayment(paymentIntentId: paymentIntentId, secret: secret) print(result.status) } catch { print(error) } ``` ## API key Use the following API key to generate your secret key and payment intent. **API_KEY**: `sk_sandbox_EtKXUrMCHU9Y7NCURtDRI9KEn0yqWDgy4JFUOeg0QNGRihcml31fxJURpfbdlx1D` ## URLs Use the following URLs to get started. ### Staging API URL `https://staging-api.dojo.dev/integration-test/tap/apple-terminal/secret` ### Payment intent URL `https://staging-api.dojo.dev/integration-test/payment-intents` ### Webhooks You can subscribe to webhooks with status updates about your payment intent using [Webhooks](https://docs.dojo.tech/payments/development-resources/webhooks). ## Error handling and SDK responses ### Capturing Errors In the event of failure during activation or taking a payment, the sdk provides several ways to capture and identify the resulted error. 1. Use `AnyDojoSDKError` to recevice the necessary details of the current error, which includers the `underlying error`, the `error code`, the `error description` povided by the SDK. 2. The sdk error code `DojoSDKErrorCode` can be obtained from the `AnyDojoSDKError` object to understand which error occured. > **Note:** We recommend taking the following actions when receiving an error. > - `retry` the current process (i.e retry activation or taking a payment) > - `block access` to tap to pay and report the issue to the relevant stakeholders. An example blocking error would be `PaymentCardReaderError.unsupported` > - `restart` activation by deactivating the current terminal using `dojoSDK.deactiveTerminal()` and starting activation again. ```bash do { let terminalStatus = try await ... print(terminalStatus) } catch { let errorValue = AnyDojoSDKError(error: error) if let code = errorValue.code { // handle the sdk error } else { // retry activation } } ``` ```bash do { let result = try await ... print(result.status) } catch { let errorValue = AnyDojoSDKError(error: error) if let readerError = errorValue.error as? PaymentCardReaderError { // handle the card reader errors } else if let sessionError = errorValue.error as? PaymentCardReaderSession.ReadError { // handle the card reader session errors } else if let code = errorValue.code { // handle the sdk error } else { // retry payment } } ``` The list of all the SDK error codes are illustrated in the diagrams below. ### Errors flow diagrams Click through the flow diagrams below to learn about how payment results and errors are structured. This flow chart describes the process flow for payment transactions, including the various steps involved from initiation to final results. An error result is a declined transaction and is associated with a `status` of 5. The error response counts as a data object. This flow chart describes the structure of the error data object. This error flow diagram includes debugging messages that can be obtained using the error data object `AnyDojoSDKError` which includes the error `code` and `description`. [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Support** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) [![](https://docs.dojo.tech/images/dojo-icons/Message.svg) **Stack Overflow** Find answers to practical questions.](https://stackoverflow.com/tags/dojo.tech) --- ## Go-live checklist(Tap-to-pay-on-pocket) To ensure you have a smooth onboarding with TaP payments, Dojo has prepared a comprehensive testing checklist that you can follow before going live with your integration. Initialize These tests relate to the POS app forcing the Dojo Pay App (TaP) [to provision](https://docs.dojo.tech/tap-to-pay-on-android#initialize). | Scenario | Steps to Reproduce | Expected Outcome | |-------|-----|----| | Provision TaP by executing the first sale to TaP from the POS | After activating the Dojo Pay App, initiate a sale of any value and take the payment. | The Dojo Pay app should provision and the transaction should complete successfully. The MPOS should then display that the sale was successful. | | Force TaP to provision through force closing while executing a sale | Close the Dojo Pay App while initiating a sale then re-open it. | The MPOS should display that the sale was cancelled and attempt to initialise again upon the next sale. | Sale These tests concern the completion of [sales](https://docs.dojo.tech/tap-to-pay-on-android#sale) and account for additional scenarios such as [splitting the bill or adding gratuities](https://docs.dojo.tech/tap-to-pay-on-android#split-bills-and-gratuities) via the Dojo Pay App. All scenarios are considered mandatory. | Scenario | Steps to Reproduce | Expected Outcome | |------------|------|---------------------------| | Execute a sale below the contactless limit. | Initiate a sale of any value below £100.00 and take the payment using a contactless card. | The MPOS should display that the sale was successful. | | Execute a sale above the contactless limit with PIN. | Initiate a sale of any value over £100.00 and take the payment using a chip and PIN. | The MPOS should display that the sale was successful. | | Execute a sale above the contactless limit BUT with PIN timeout. | Initiate a sale of any value over £100.00 and present the card, however, allow the payment to time-out by not entering the PIN. | The MPOS should display that the sale was not successful. | | Execute a sale below the contactless limit BUT with timeout. | Initiate a sale of any value below £100.00 and allow the payment to time-out by not presenting a card. | The MPOS should display that the sale was not successful. | | Execute a sale below the contactless limit BUT cancel the sale. | Initiate a sale of any value below £100.00 and select the cancel button. | The MPOS should display that the sale was cancelled. | | Execute a sale below the contactless limit BUT lose connectivity. | Initiate a sale of any value below £100.00 and disable the currently used connection method, then return to the MPOS. | The MPOS should display that the transaction was not successful. | | Execute a sale below the contactless with gratuity. | Initiate a sale of any value below £100.00, add a gratuity within the Dojo Pay App, then take the payment using a contactless card. | The MPOS should display that the sale was successful and record the gratuity separate to the base value. | | Execute a sale below the contactless limit with bill splitting. | Initiate a sale of any value below £100.00, use the Dojo Pay App to split the bill between multiple payees, then take all payments using a contactless card. | The MPOS should display that the sale was successful and present each payment individually. | | Execute a sale below the contactless limit with bill splitting failing the second tx. | Initiate a sale of any value below £100.00, use the Dojo Pay App to split the bill between two payees, take the first payment using a contactless card and then cancel the second payment. | The MPOS should display that only one sale was successful and present the oustanding balance to be paid. | Refund These tests cover [refunds](https://docs.dojo.tech/tap-to-pay-on-android#refund) via TaP. Refunds are a mandatory aspect of TaP to Pay on Pocket and any sales completed should therefore be themselves retrievable and refundable to the customer. | Scenario | Steps to reproduce | Expected outcome | |----------|-------|---------| | Execute a refund below the contactless limit | Execute a refund below the contactless limit. | The MPOS should display that the refund was successful. | | Execute a refund above the contactless limit with PIN | Initiate a refund of any value over £100.00 and complete the transaction using a chip and PIN. | The MPOS should display that the refund was successful. | | Execute a refund above the contactless limit BUT with PIN timeout | Initiate a refund of any value over £100.00 and present the card, however, allow the transaction to time-out by not entering the PIN. | The MPOS should display that the refund was not successful. | | Execute a refund below the contactless limit BUT with timeout | Initiate a refund of any value below £100.00 and allow the transaction to time-out by not presenting a card. | The MPOS should display that the refund was not successful. | | Execute a refund below the contactless limit BUT cancel the refund | Initiate a refund of any value below £100.00 and select the cancel button. | The MPOS should display that the refund was cancelled. | --- ## Tap to Pay on Pocket > Initiate and accept contactless payments from your POS application on the Dojo Pocket. ## Overview > **Note:** The code samples in this document use [kotlin](https://developer.android.com/kotlin). **Tap to Pay on Pocket** (TaP for short) allows users to process mobile point of sale (MPos) transactions via a 3rd Party POS Android application loaded onto their **[Dojo Pocket](https://dojo.tech/products/dojo-pocket/)**, and receive in-person contactless payments from physical payment cards and other mobile devices by making use of the Pocket's built-in **[NFC](https://developer.android.com/develop/connectivity/nfc)** reader and Dojo Pay App. Facilitating communication between a POS application and the Dojo Pay App is [intent-based messaging](https://developer.android.com/guide/components/intents-filters), one of the [Inter-Process-Communication (IPC)](https://developer.android.com/guide/components/processes-and-threads#IPC) mechanisms that allow Android components to communicate with one another. User-defined intent messages with optional payloads are passed between processes (for example, apps and [Activities](https://developer.android.com/reference/android/app/Activity)) and parsed by the receiving component and acted upon. ## Intent sequence Click one of the intent endpoints in the sequence below to jump to the relevant section. - TaP request: [Initializes the TaP application](https://docs.dojo.tech/plugins/woocommerce/introduction#request-message) - POS response: [Sends initialization results](https://docs.dojo.tech/plugins/woocommerce/introduction#response) - TaP: [Start](https://docs.dojo.tech/plugins/woocommerce/introduction#request-message-1) or [refund](https://docs.dojo.tech/plugins/woocommerce/introduction#request-message-2) transaction - POS: Send [sale](https://docs.dojo.tech/plugins/woocommerce/introduction#response-1) or [refund](https://docs.dojo.tech/plugins/woocommerce/introduction#response-2) results - TaP: [Send last transaction results](https://docs.dojo.tech/plugins/woocommerce/introduction#request-message-3) - POS: [Receive last transaction results](https://docs.dojo.tech/plugins/woocommerce/introduction#response-3) - TaP: [Request a split bill and set gratuity information](https://docs.dojo.tech/plugins/woocommerce/introduction#request-message-4) - POS: [Send split bill and gratuity information](https://docs.dojo.tech/plugins/woocommerce/introduction#response-4) ### Format Intents and extras are written as literal string values, but payload data types can be formatted as string, boolean, or integer. ```bash val intent = Intent("com.dojo.action.ACTION_NAME") intent.putExtra("com.dojo.extra.EXTRA_NAME", activation_code: String) ``` ### Additional flags Intents must be created using the [`SingleTop` flag](https://developer.android.com/guide/components/activities/tasks-and-back-stack#TaskLaunchModes). This means if, for example, a sale request is sent when an identical sale is already at the top of the stack, the system will reuse that existing instance instead of creating a new one. ```bash val intent = Intent("com.dojo.action.INIT") intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP) ``` ## Initialize ![](https://docs.dojo.tech/images/TaP/tap-init-flow.jpg) **Flow diagram: Tap Init Flow** ```mermaid graph TD Start["val intent = Intent('com.dojo.action.INIT')"] --> Provisions[Device Provisions] Provisions -->|Device has never been activated| Activation[Device Activation FlowCompleted within Dojo Pay App] Provisions --> Complete Activation --> Complete Complete[INIT_COMPLETECheck OnActivityResult] Complete --> ResultFalse[INIT_RESULT false] Complete --> ResultTrue[INIT_RESULT true] style ResultFalse fill:#f96,stroke:#333 style ResultTrue fill:#3f3,stroke:#333 style Provisions fill:#d1f2eb,stroke:#333 style Complete fill:#b8c2f2,stroke:#333 ``` Before defining any sale, refund, or split bill and gratuity logic, the first step is to initialize and provision TaP. ### Request message Begin the initialization and provisioning process: ```kotlin val intent = Intent("com.dojo.action.INIT") ``` TaP provisioning may take up to two minutes to complete. ### Prerequisites * The device must not be in [developer mode](https://developer.android.com/studio/debug/dev-options), or connected via [Android Debug Bridge (ADB)](https://developer.android.com/tools/adb) to a client. * The [device system images](https://developer.android.com/topic/generic-system-image) must not be modified (no custom [bootloader](https://source.android.com/docs/core/architecture/bootloader) or SU binary). * The bootloader [must be locked](https://source.android.com/docs/core/architecture/bootloader/locking_unlocking). * The device must be [NFC-enabled](https://support.google.com/wallet/answer/12200245). Should these checks fail, TaP will not be able to provision. ### TaP Action Initialization is currently a UI-interactive process in TaP, requiring user input to enter the activation code and complete the device setup procedure. In future releases, this third party driven initialization will become a silent background process in TaP, with no UI interaction required. Any required setup data would be passed as a payload within the intent message. ### Response TaP will return its response in the `onActivityResult` API call of the calling activity: * An `INIT_COMPLETE` response is returned to indicate the status of the initialization. * The `INIT_RESULT` and `INIT_RESULT_DETAIL` extra fields reflect the initialization status. * `INIT_RESULT` returns a boolean value of `true` if it is successful and `false` if it is not. * The `INIT_RESULT_DETAIL` value will be either `OK` if initialization completes successfully or `COMPLETED` if it was already initialised before the call was made. * If there are any problems an error code will be provided as a string. This message returns TaP initialization status information to the POS: ```bash val intent = Intent("com.dojo.action.INIT_COMPLETE") with(intent) { putExtra("com.dojo.extra.INIT_RESULT", [true|false] :Boolean) putExtra("com.dojo.extra.INIT_RESULT_DETAIL", "OK") } with(requireActivity()) { setResult(Activity.RESULT_OK, intent) finish() } ``` ### Required POS Action In the [`onActivityResult`](https://learn.microsoft.com/en-us/dotnet/api/android.app.activity.onactivityresult?view=net-android-34.0) Activity callback: ```kotlin val initResult = data?.getBooleanExtra("com.dojo.extra.INIT_RESULT") val initResultDetail = data?.getStringExtra("com.dojo.extra.INIT_RESULT_DETAIL") ``` The POS should parse this message to determine whether the TaP initialization succeeded or failed by parsing the `INIT_RESULT` boolean. Further information on the failure status will be available in the `INIT_RESULT_DETAIL` string. Error codes include: * `E1` - a payment session failed to start. * `A10` - a provisioning error occurred. * `T1` - a timeout caused the provisioning to be cancelled. The POS app should respond to the messages using one of the following approaches: * No action required in the event of a successful device initialization. * Re-trying the initialization. * Notifying the user of a technical fault after multiple retries. ## Sale ### Request message This message is to be used by the POS to request TaP to begin a contactless transaction. Sender example code: ```bash val intent = Intent("com.dojo.action.SALE") intent.putExtra("com.dojo.extra.BASE_AMOUNT", amount_in_pennies: Int) ``` ### Prerequisites TaP must have been previously provisioned using `INIT` in order for this request to succeed. ### TaP Action On receiving the request, TaP will begin a transaction, display the contactless acceptance screen, and wait for the presentation of a contactless EMV card. ### Response The user should present a card to the device for contactless payment. TaP will then process the transaction, contact the acquiring bank for authorization, then show the result to the user. Should the transaction fail, the reason will be displayed to the user (for example, card declined or card expired). These status codes will be returned to the POS in the response message. This message returns transaction status and payment data to the POS. Sender example (TaP): ```bash val intent = Intent("com.dojo.action.TX_COMPLETE") intent.putExtra("com.dojo.extra.SALE_STATUS", "OK") intent.putExtra("com.dojo.extra.TRANSACTION_RESULT", "AUTHORISED") // enum: AUTHORISED, DECLINED, CANCELLED, FAILED intent.putExtra("com.dojo.extra.TRANSACTION_ID", "123456789") intent.putExtra("com.dojo.extra.AUTH_CODE", "654321") intent.putExtra("com.dojo.extra.BASE_AMOUNT", 1000) intent.putExtra("com.dojo.extra.GRATUITY_AMOUNT", 150) intent.putExtra("com.dojo.extra.PAYMENT_METHOD", "CONTACTLESS") // enum: KEYED, MANUAL_ENTRY, SWIPE, ICC_CHIP, CONTACTLESS, UNKNOWN intent.putExtra("com.dojo.extra.CARDHOLDER_VERIFICATION_METHOD", "PIN") // enum: PIN, SIGNATURE intent.putExtra("com.dojo.extra.CARD_SCHEME", "VISA") // enum: VISA, MASTERCARD, MAESTRO, AMERICAN_EXPRESS, DISCOVER, DINERS, UNION_PAY, JCB, UNKNOWN intent.putExtra("com.dojo.extra.CARD_APPLICATION_LABEL", "VISA DEBIT") intent.putExtra("com.dojo.extra.CARD_APPLICATION_ID", "A0000000031010") intent.putExtra("com.dojo.extra.CARD_PAN", "************0226") // masked PAN with(requireActivity()) { setResult(Activity.RESULT_OK, intent) finish() } ``` ### Expected POS Action The POS should parse this message to determine whether the transaction succeeded or failed by parsing the `TRANSACTION_RESULT` string along with the fields listed below. `OnActivityResult` example: ```bash val transactionResult = data?.getStringExtra("com.dojo.extra.TRANSACTION_RESULT") val TransactionId = data?.getStringExtra("com.dojo.extra.TRANSACTION_ID") val AuthCode = data?.getStringExtra("com.dojo.extra.AUTH_CODE") ``` ## Refund ### Request message This message is to be used by the POS to request TaP to begin a contactless refund transaction. Sender example code: ```bash val intent = Intent("com.dojo.action.REFUND") intent.putExtra("com.dojo.extra.BASE_AMOUNT", amount_in_pennies: Int) ``` ### Prerequisites TaP must have been previously provisioned using `INIT` in order for this request to succeed. ### TaP Action On receiving the request, TaP will begin a transaction, display the contactless acceptance screen, and wait for the presentation of a contactless EMV card. The user should present a card to the device for contactless payment. TaP will then process the refund transaction, contacting the acquiring bank for authorization and show the result to the user. ### Response This message returns transaction status and payment data to the POS. Should the transaction fail, the reason will be displayed to the user (for example, card declined or card expired). These status codes will be returned to the POS in the response message. Sender example (TaP): ```bash val intent = Intent("com.dojo.action.TX_COMPLETE") intent.putExtra("com.dojo.extra.REFUND_STATUS, refundStatus: String) intent.putExtra("com.dojo.extra.TRANSACTION_RESULT", transactionResult: String (enum: SUCCESSFUL, DECLINED, CANCELLED, UNSUCCESSFUL)) intent.putExtra("com.dojo.extra.TRANSACTION_ID", transactionId: String) intent.putExtra("com.dojo.extra.AUTH_CODE", authCode: String) intent.putExtra("com.dojo.extra.BASE_AMOUNT", baseAmount: Integer) intent.putExtra("com.dojo.extra.PAYMENT_METHOD", paymentMethod: String (enum: KEYED, SWIPED, ICC_CHIP, CONTACTLESS)) intent.putExtra("com.dojo.extra.CARDHOLDER_VERIFICATION_METHOD", cardholderVerificationMethod: String (enum: NONE, PIN, DEVICE)) intent.putExtra("com.dojo.extra.CARD_SCHEME", cardScheme: String (enum: VISA, MASTERCARD, MAESTRO, AMEX, DISCOVER, DINERS, UNKNOWN)) intent.putExtra("com.dojo.extra.CARD_APPLICATION_LABEL", cardApplicationLabel: String) intent.putExtra("com.dojo.extra.CARD_APPLICATION_ID", cardApplicationId: String) with(requireActivity()) { setResult(Activity.RESULT_OK, intent) finish() } ``` | Key (literal string) | Value | Type | |-------------------------------------------|---------------------------|----------| | `com.dojo.extra.REFUND_STATUS` | `NOT_PROVISIONED` / `OK` | String | | `com.dojo.extra.BASE_AMOUNT` | Base transaction amount | Integer | | `com.dojo.extra.TRANSACTION_RESULT` | `AUTHORISED` / `CANCELLED` / `DECLINED` / `FAILED` | String | | `com.dojo.extra.AUTH_CODE` | Tx Authorization Code | String | | `com.dojo.extra.PAYMENT_METHOD` | Contactless | String | | `com.dojo.extra.CARDHOLDER_VERIFICATION_METHOD` | Contactless/PIN | String | | `com.dojo.extra.CARD_SCHEME` | Mastercard/Visa/Amex/Discover | String | | `com.dojo.extra.CARD_APPLICATION_LABEL` | EMV application label | String | | `com.dojo.extra.CARD_APPLICATION_ID` | EMV application ID | String | | `com.dojo.extra.TRANSACTION_ID` | TaP transaction ID | String | ### Expected POS Action The POS should parse this message to determine whether the refund succeeded or failed: * `TRANSACTION_RESULT` (string) `OnActivityResult` example: ```bash val transactionResult = data?.getStringExtra("com.dojo.extra.TRANSACTION_RESULT") val TransactionId = data?.getStringExtra("com.dojo.extra.TRANSACTION_ID") val AuthCode = data?.getStringExtra("com.dojo.extra.AUTH_CODE") ``` ## Last transaction details ### Request message This message is used by the POS to request details of the last executed transaction. It should be utilized in scenarios where the POS fails to receive a response from the preceding transaction. Example situations include: * The TaP app failed to send the response due to an internal failure. * The POS app failed during processing the response. * The device restarted before the POS could process the response. ```kotlin val intent = Intent("com.dojo.action.LAST_TX") ``` ### Prerequisites TaP must have been previously provisioned using `INIT` for this request to succeed. ### TaP Action Upon receiving this message, TaP will return the available details from the last completed transaction, regardless of the transaction outcome (authorized, declined, or failed). It is not currently possible to request details for a specific transaction. #### Response The `LAST_TX_COMPLETE` message is returned to the caller in the `onActivityResult` activity callback handler, containing transaction status information. The field `SPLIT_BILL` indicates whether the last transaction was split between two or more customers. Fields default to empty strings where data was not successfully retrieved, for example, where card data could not be fetched successfully. The payload contains the following data: | Key (literal string) | Value | Type | |---------------------------------------------|------------------------------------|---------| | `com.dojo.extra.SPLIT_BILL` | `False` | Boolean | | `com.dojo.extra.TX_STATUS` | `OK` | String | | `com.dojo.extra.BASE_AMOUNT` | Base transaction amount | Integer | | `com.dojo.extra.GRATUITY_AMOUNT` | Gratuity transaction amount | Integer | | `com.dojo.extra.TRANSACTION_RESULT` | `AUTHORISED` / `CANCELLED` / `DECLINED` / `FAILED` | String | | `com.dojo.extra.AUTH_CODE` | Tx Authorization Code | String | | `com.dojo.extra.PAYMENT_METHOD` | `CONTACTLESS` / `KEYED` | String | | `com.dojo.extra.CARDHOLDER_VERIFICATION_METHOD` | Contactless / PIN | String | | `com.dojo.extra.CARD_SCHEME` | `Mastercard` / `Visa` / `Amex` / `Discover` | String | | `com.dojo.extra.CARD_APPLICATION_LABEL` | EMV application label | String | | `com.dojo.extra.CARD_APPLICATION_ID` | EMV application ID | String | | `com.dojo.extra.TRANSACTION_ID` | TaP transaction ID | String | ```bash with(intent) { putExtra("com.dojo.extra.SPLIT_BILL", false) putExtra("com.dojo.extra.TX_STATUS", "OK") putExtra("com.dojo.extra.TRANSACTION_RESULT", toThirdPartyTxResult()) putExtra("com.dojo.extra.AUTH_CODE", txItem.authCode) putExtra("com.dojo.extra.PAYMENT_METHOD", txItem.paymentMethod.name) putExtra("com.dojo.extra.CARDHOLDER_VERIFICATION_METHOD", txItem.cvm.name) putExtra("com.dojo.extra.CARD_SCHEME", txItem.cardScheme.name) putExtra("com.dojo.extra.CARD_APPLICATION_LABEL", txItem.applicationLabel) putExtra("com.dojo.extra.CARD_APPLICATION_ID", txItem.applicationId.value) putExtra("com.dojo.extra.TRANSACTION_ID", txItem.txId.value) putExtra("com.dojo.extra.BASE_AMOUNT", txItem.baseAmount.value) putExtra("com.dojo.extra.GRATUITY_AMOUNT", txItem.gratuityAmount.value) } with(requireActivity()) { setResult(Activity.RESULT_OK, intent) finish() } ``` ## Split bills At the payment stage, the user can split a bill into constituent transactions and then recombine those into a bundle. These are the response schema associated with a bundled collection, as a whole: | Key (literal string) | Value | Type | |-------------------------------------------|---------------------------|----------| | `com.dojo.extra.PAYMENTS_MADE` | Number of payments made | Integer | | `com.dojo.extra.TOTAL_BASE_AMOUNT` | Total amount to be paid in pennies | Integer | | `com.dojo.extra.TOTAL_PAID_AMOUNT` | Total amount paid in pennies | Integer | | `com.dojo.extra.TOTAL_GRATUITY_AMOUNT` | Total gratuity amount paid in pennies | String | | `com.dojo.extra.PAYMENT_KEYS` | List of payment keys | List(String) | The value passed for `PAYMENT_KEYS` will be a list of strings. These keys are associated with individual transactions inside the split bill bundle. The details of each transaction can then be extracted as a bundle from the intent response using that key. ### Individual bundle item schema You can extract individual transaction information from a split bill bundle: ```bash val baseAmount = bundle.getInt("com.dojo.extra.BASE_AMOUNT", -1) val gratuityAmount = bundle.getInt("com.dojo.extra.GRATUITY_AMOUNT", -1) val txResult = bundle.getString("com.dojo.extra.TRANSACTION_RESULT") val authCode = bundle.getString("com.dojo.extra.AUTH_CODE") val txId = bundle.getString("com.dojo.extra.TRANSACTION_ID") val paymentMethod = bundle.getString("com.dojo.extra.PAYMENT_METHOD") if (paymentMethod == "KEYED") return val cvmString = bundle.getString("com.dojo.extra.CARDHOLDER_VERIFICATION_METHOD") val cardScheme = bundle.getString("com.dojo.extra.CARD_SCHEME") val appLabel = bundle.getString("com.dojo.extra.CARD_APPLICATION_LABEL") val appId = bundle.getString("com.dojo.extra.CARD_APPLICATION_ID") ``` These response schema are associated with individual transactions extracted from a bundle: | Key (literal string) | Value | Type | |-------------------------------------------|---------------------------|----------| | `com.dojo.extra.TX_STATUS` | `NOT_PROVISIONED` | OK | String | | `com.dojo.extra.BASE_AMOUNT` | Base transaction amount | Integer | | `com.dojo.extra.GRATUITY_AMOUNT` | Gratuity transaction amount | Integer | | `com.dojo.extra.TRANSACTION_RESULT` | `AUTHORISED` / `DECLINED` / `FAILED` | String | | `com.dojo.extra.AUTH_CODE` | Tx Authorisation Code | String | | `com.dojo.extra.PAYMENT_METHOD` | Contactless | String | | `com.dojo.extra.CARDHOLDER_VERIFICATION_METHOD` | Contactless/PIN | String | | `com.dojo.extra.CARD_SCHEME` | Mastercard/Visa/Amex/Discover | String | | `com.dojo.extra.CARD_APPLICATION_LABEL` | EMV application label | String | | `com.dojo.extra.CARD_APPLICATION_ID` | EMV application ID | String | | `com.dojo.extra.TRANSACTION_ID` | TaP transaction ID | String | [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Support** Our Partner Enablement team is always happy to help with any questions you have.](mailto:partnertech@dojo.tech) [![](https://docs.dojo.tech/images/dojo-icons/Message.svg) **Stack Overflow** Find answers to practical questions.](https://stackoverflow.com/tags/dojo.tech) --- ## Go-live checklist(Checkout-page) > Check off these steps before launching your integration in production. The following steps ensure you have a complete implementation. ## Test in the sandbox Before going live, test your integration in the [sandbox](https://docs.dojo.tech/development-resources/portal#sandbox-and-production-environments). For each payment method that you offer: * Make a successful payment. * Make an unsuccessful payment. Use the following test card numbers to make payments: ## Check the result Make your first live API call and check that your production key works. Open your checkout page to see the result. For the production environment, there should be no yellow **Sandbox** label. --- ## Prebuilt checkout page >Discover the Dojo Prebuilt Checkout. Dojo offers our own accessible, lightweight prebuilt checkout UI to simplify your payment implementations. It is fully secure, and has been designed to be as customizable and responsive as possible. ![Online checkout](https://docs.dojo.tech/images/online-checkout.jpg) ## What's in the box? - The prebuilt payment page, hosted by Dojo. - [Card payments and Wallet payments (Apple Pay and Google Pay)](https://docs.dojo.tech/plugins/woocommerce/checkout-page/configuration#add-payment-methods). - Validation of card details. - Email receipts. - Responsive design. - [Strong Customer Authentication (SCA)](https://www.fca.org.uk/firms/strong-customer-authentication). - [Address forms to collect customer details](https://docs.dojo.tech/plugins/woocommerce/checkout-page/configuration#collect-billing-address-shipping-details-and-customer-email). --- ## Let's get started [![Let's get started](https://docs.dojo.tech/images/dojo-icons/BookBookmark.svg) **Step-by-step guide** Learn how to implement a Checkout Page ready to accept payments.](checkout-page/step-by-step-guide) --- ## Optional configuration >Learn how to activate additional features for your checkout page. Additional configuration is a useful way to capture extra information about your customers, and you can set up whichever fields best meet the needs of your implementation. For example, a lot of merchants operate online stores and send things to their customers, so the shipping address is one of the most commonly-used optional fields. A billing address is required even more frequently, in cases where a transaction does not involve physical items. The following examples include the other most common optional configurable payment fields. See the [API reference](https://docs.dojo.tech/api) for the full list of configurable fields. - [Add payment methods](https://docs.dojo.tech/plugins/woocommerce/introduction#add-payment-methods) Integrate Apple Pay and Google Pay wallets in addition to card payments. - [Collect billing address, shipping details, and customer email](https://docs.dojo.tech/plugins/woocommerce/introduction#collect-billing-address-shipping-details-and-customer-email) Use your checkout page to capture useful information about your customer. - [Redirect to your success page](https://docs.dojo.tech/plugins/woocommerce/introduction#redirect-to-your-success-page) Show your success page to customers. - [Show detailed information about the order and taxes](https://docs.dojo.tech/plugins/woocommerce/introduction#show-detailed-information-about-the-order-and-taxes) Set up the information that you want to show to customers. - [Add information about your company](https://docs.dojo.tech/plugins/woocommerce/introduction#add-information-about-your-company) Customize the checkout page title. ## Add payment methods ![](https://docs.dojo.tech/images/add-payment-methods.png) By default, the checkout page supports only card payments. To enable Apple Pay and Google Pay wallets, pass `"Card","Wallet"` in `paymentMethods`, for example: ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' \ --data '{ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order-0001", "paymentMethods": [ "Card", "Wallet" ] }' ``` You must [verify your domain](https://developer.apple.com/documentation/applepaywebmerchantregistrationapi/preparing_merchant_domains_for_verification) for Apple Pay. ## Collect billing address, shipping details, and customer email ![](https://docs.dojo.tech/images/billing-and-shipping-details.png) You can add a form to collect billing address, shipping details, and the customer email to the checkout page, by passing `collectionRequired: true` in `config.billingAddress`, `config.shippingDetails`, and `config.customerEmail`: ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' \ --data '{ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order-0001", "config": { "customerEmail": { "collectionRequired": true }, "billingAddress": { "collectionRequired": true }, "shippingDetails": { "collectionRequired": true } } }' ``` ## Redirect to your success page After your customer submits payment information on the checkout page, Dojo processes the payment and redirects the customer to the success page. You can, alternately, redirect the customer to another page of your choice after payment, by passing the URL in `config.redirectUrl`: ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' \ --data '{ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order-0001", "config": { "redirectUrl": "http://mymerchantsite.com/checkout/success_pay" } }' ``` ## Show detailed information about the order and taxes ![](https://docs.dojo.tech/images/show-detailed-information.png) You can add information about each position in the order to the checkout page, to do it, pass this data to `itemLines`. Additionally, you can add information about any taxes or fees included in the order using `taxLines`. Item and tax amounts do not affect the payment intent amount. To add total due to the checkout page, pass `showTotal: true` in `config.details`. This value will be the same as the [payment intent](https://docs.dojo.tech/manage-payments/payment-intent) amount. ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' \ --data '{ "amount": { "value": 1510, "currencyCode": "GBP" }, "reference": "Order-0001", "itemLines": [ { "id": "item 1", "quantity": 4, "caption": "Dog socks", "amountTotal": { "value": 400, "currencyCode": "GBP" } }, { "id": "item 5", "quantity": 1, "caption": "Dog bandana", "amountTotal": { "value": 600, "currencyCode": "GBP" } } ], "taxLines": [ { "id": "vat", "caption": "VAT", "subCaption": "10%", "amountTotal": { "value": 10, "currencyCode": "GBP" } }, { "id": "delivery", "caption": "Delivery", "amountTotal": { "value": 500, "currencyCode": "GBP" } } ], "config": { "details": { "showTotal": true } } }' ``` ## Add information about your company ![](https://docs.dojo.tech/images/show-title.png) You can customize the checkout page’s title, for example, by adding your company name. To do this, pass a title in `config.title`. If you leave this parameter empty it will default to the trading name you provided to Dojo at sign-up. ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' \ --data '{ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order-0001", "config": { "title": "The Company" } }' ``` --- ## More information [![](https://docs.dojo.tech/images/dojo-icons/TickCircle.svg) **Check your integration** Check off these steps before launching your integration in production.](checklist) [![](https://docs.dojo.tech/images/dojo-icons/TerminalWindow.svg) **API reference** See the API reference for a complete list of parameters you use.](/api) --- ## Customization >Learn about customizing your prebuilt checkout page. You can customize how your prebuilt checkout page looks by adding your logo. ## Ready to get started? [![](https://docs.dojo.tech/images/dojo-icons/Wrench.svg) **Add your logo** Customize your payment page to add your own logo.](https://support.dojo.tech/hc/en-gb/articles/5235120320924-Add-your-logo-to-your-payment-links) --- ## Step-by-step guide(Checkout-page) >Learn how to implement our Checkout Page to accept payments. A checkout page integration contains the following: - Server-side: one API request to create a payment intent. - Client-side: a redirect to the Checkout Page. - WebHooks: a server-side endpoint to receive information about the payment. The payment flow is: 1. The customer visits the merchant's site and clicks the Checkout button. 2. The merchant client-side sends the customer's purchases information to the merchant server-side, and the merchant server-side sends this information to the Dojo server and [creates a payment intent](https://docs.dojo.tech/plugins/woocommerce/introduction#step-1-create-a-payment-intent). 3. The merchant client-side [redirects the customer](https://docs.dojo.tech/plugins/woocommerce/introduction#step-2-redirect-your-customer-to-dojo-checkout-page) to the Prebuilt Checkout Page, which is hosted by Dojo. 4. The Prebuilt Checkout Page collects the customer's payment details, sends them to the Dojo servers, and redirects the customer to the results page. 5. The merchant server receives a [WebHook notification](https://docs.dojo.tech/plugins/woocommerce/introduction#step-3-handle-post-payment-events) when the payment is completed. ![](https://docs.dojo.tech/images/flow-checkout-page.jpg) **Flow diagram: Flow Checkout Page** ```mermaid sequenceDiagram actor C as Customer participant DC as dojo Client-side participant MC as Merchant Client-side participant MS as Merchant Server-side participant DS as dojo Server-side C->>MC: Clicks "Checkout" MC->>MS: Sends information about customer purchases MS->>DS: POST /payment-intents DS-->>MS: PaymentIntent object MS-->>MC: PaymentIntentId MC->>DC: Redirects to Prebuilt Checkout Page C->>DC: Enters payment details and clicks "Pay" DS-->>DC: Redirects to the result page DS->>MS: Sends webhooks ``` **LLM walkthrough: complete Checkout Page happy path** Use this template when your server creates the payment intent and the browser only needs to redirect the customer to Dojo Checkout. All Dojo REST calls in this walkthrough use: - `Authorization: Basic ` (literal `Basic ` prefix; do not base64-encode `api_key:`) - `version: 2026-02-27` - `Content-Type: application/json` **1. Create the payment intent with a redirect URL** **POST** `/payment-intents` **Request body** ```json { "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order-0001", "description": "Hosted checkout payment for basket 245", "config": { "redirectUrl": "https://merchant.example/checkout/success" } } ``` **Response body** ```json { "id": "pi_sandbox_G_FeegU8WESxtY_Nct8jqw", "captureMode": "Auto", "status": "Created", "paymentMethods": [ "Card" ], "amount": { "value": 1000, "currencyCode": "GBP" }, "totalAmount": { "value": 1000, "currencyCode": "GBP" }, "refundedAmount": 0, "createdAt": "2024-04-07T23:25:44.802258Z", "updatedAt": "2024-04-07T23:25:44.802258Z", "reference": "Order-0001", "description": "Hosted checkout payment for basket 245", "paymentLink": "https://pay.dojo.tech/checkout/pi_sandbox_G_FeegU8WESxtY_Nct8jqw", "paymentEvents": [], "terminalSessionHistory": [] } ``` **2. Return the checkout URL to the browser and redirect the customer** Your own backend can return the payment link it received from Dojo: ```json { "paymentIntentId": "pi_sandbox_G_FeegU8WESxtY_Nct8jqw", "paymentLink": "https://pay.dojo.tech/checkout/pi_sandbox_G_FeegU8WESxtY_Nct8jqw" } ``` Then redirect the browser to `paymentLink`: ```js window.location.replace("https://pay.dojo.tech/checkout/pi_sandbox_G_FeegU8WESxtY_Nct8jqw"); ``` **3. Handle the success page by fetching the latest payment status** When the browser lands on your `redirectUrl`, load the `paymentIntentId` you stored for the checkout session and call Dojo from your backend to render the latest status on the page. **GET** `/payment-intents/pi_sandbox_G_FeegU8WESxtY_Nct8jqw` **Response body** ```json { "id": "pi_sandbox_G_FeegU8WESxtY_Nct8jqw", "captureMode": "Auto", "status": "Captured", "paymentMethods": [ "Card" ], "amount": { "value": 1000, "currencyCode": "GBP" }, "totalAmount": { "value": 1000, "currencyCode": "GBP" }, "refundedAmount": 0, "reference": "Order-0001", "description": "Hosted checkout payment for basket 245", "paymentDetails": { "transactionId": "19e4535e-ef6e-48e2-90be-d2b313c1cefd", "transactionDateTime": "2024-07-25T08:49:20.973410318Z", "message": "DEPOSITED", "authCode": "123456", "card": { "cardNumber": "44565300****1096", "cardName": "test", "expiryDate": "2024-12-31", "cardType": "VISA", "entryMode": "Contactless", "verificationMethod": "Pin" } }, "paymentEvents": [ { "transactionId": "19e4535e-ef6e-48e2-90be-d2b313c1cefd", "transactionDateTime": "2024-07-25T08:49:20.973410318Z", "eventType": "Captured", "authCode": "123456", "cardNumber": "44565300****1096", "expiryDate": "2024-12-31", "cardType": "VISA", "cardholderName": "test", "paymentMethodId": "" } ] } ``` Use the success page for customer UX only. Treat the webhook as the final source of truth for order fulfilment. **4. Subscribe to and verify the webhook notification** **POST** `/webhooks` **Request body** ```json { "events": [ "payment_intent.status_updated" ], "url": "https://merchant.example/webhooks/dojo" } ``` **Response body** ```json { "id": "ws_aNkU6yob0vOMxUlghg2oynUw", "accountId": "acc_4z3k2xP17e1JQY", "events": [ "payment_intent.created", "payment_intent.status_updated" ], "url": "https://merchant.example/webhooks/dojo", "description": "Demo Webhooks", "secrets": [ { "id": "sc_qNkU6yob0vOMxUlb2oynUw", "value": "U3Vic2NyaXB0aW9uUmVzcG9uc2VFeGFtcGxlIDogSUV4YW1wbGVQcm92aWRlcjxTdWJ", "createdAt": "2023-12-13T14:15:01", "lastUsedAt": "2023-12-16T13:44:03.3242202Z", "isActive": true } ], "createdAt": "2023-03-30T12:21:04.143Z", "updatedAt": "2023-03-30T12:21:04.143Z" } ``` **Incoming webhook payload** ```json { "id": "evt_hnnHxIKR_Uy6bhZCusCltw", "event": "payment_intent.status_updated", "accountId": "acc_test", "createdAt": "2024-07-25T08:49:24.761Z", "data": { "paymentIntentId": "pi_sandbox_G_FeegU8WESxtY_Nct8jqw", "paymentStatus": "Captured", "captureMode": "Auto" } } ``` ## How to process a payment Step-by-step guide: 1. [Create a payment intent](https://docs.dojo.tech/plugins/woocommerce/introduction#step-1-create-a-payment-intent). 2. [Redirect your customer to the Dojo Checkout Page](https://docs.dojo.tech/plugins/woocommerce/introduction#step-2-redirect-your-customer-to-dojo-checkout-page). 3. [Handle post-payment events](https://docs.dojo.tech/plugins/woocommerce/introduction#step-3-handle-post-payment-events). 4. [Test and go live](https://docs.dojo.tech/plugins/woocommerce/introduction#step-4-test-and-go-live). ### Before you start ### Step 1. Create a payment intent To create a payment intent, the following parameters are required: - `amount`: This includes the currency and value, in minor units, for example, "1000" for 10.00 GBP. - `reference`: Your unique reference for the payment intent. Here's an example of how to create a payment intent for 10 GBP on your server-side: ```py title="server.py" @app.route('/checkout', methods=['GET', 'POST']) def hello(): # POST request if request.method == 'POST': print(request.get_json()) # parse as JSON conn = http.client.HTTPSConnection("api.dojo.tech") # call post payment-intent payload = json.dumps({ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order 245" }) headers = { 'Content-Type': "application/json", 'Version': "2024-02-05", 'Authorization': "Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ" # <-- Change to your secret key } conn.request("POST", "/payment-intents/", payload, headers) # handling the response from POST res = conn.getresponse() data = res.read() resp_data = {} resp_data['id'] = json.loads(data)["id"] json_data = json.dumps(resp_data) resp = app.response_class( response=json_data, mimetype='application/json' ) return resp ``` See the [API reference](https://docs.dojo.tech/api#operation/PaymentIntents_CreatePaymentIntent) for a complete list of parameters that can be used for payment intent creation. ### Step 2. Redirect your customer to Dojo Checkout Page After receiving the request, Dojo creates a payment intent and returns its unique ID: ```json { "id": "pi_CggWPWfehUWgVNnDdsdLMQ", ... } ``` Return this ID to the client-side and use it to create a link in the following format: `https://pay.dojo.tech/checkout/{{id}}` Redirect your customer to the link on your client-side: ```js title="online-checkout-client.html" .then(response => response.json()) .then(function (data) { var redirectLink = "https://pay.dojo.tech/checkout/" + data.id window.location.replace(redirectLink) }); ``` After your customer fills payment information on the checkout page, Dojo processes the payment and redirects the customer to the success page. ### Step 3. Handle post-payment events ### Step 4. Test and go live Before going live, test your integration using the test card numbers: --- ## Next steps [![](https://docs.dojo.tech/images/dojo-icons/AnchorSimple.svg) **Set up notification webhooks** Use webhooks to receive updates related to your payments.](/development-resources/webhooks) [![](https://docs.dojo.tech/images/dojo-icons/Settings.svg) **Configure Checkout Page** Find out how to add another payment method or shipping address form to the page.](configuration) [![](https://docs.dojo.tech/images/dojo-icons/TickCircle.svg) **Check your integration** Check off these steps before launching your integration in production.](checklist) [![](https://docs.dojo.tech/images/dojo-icons/Filters.svg) **Manage payments** Learn how to capture or reverse payments, retrieve payment details or change payments amount.](../../../manage-payments) --- ## Card >Learn how you can embed the prebuilt Dojo Card Component into your checkout page. The Dojo Card Component is a prebuilt JavaScript component for accepting payments on your checkout page. Use this integration option when you want full control over the payment flow and the look of your checkout page. In terms of implementation, the integration contains: - Server-side: one API request to create a payment intent. - Client-side: set up Dojo Card Component, which securely sends payment data to our server. - Webhooks: server-side endpoint to receive information about the payment. The payment flow is: 1. The customer visits the merchant's site and clicks the Checkout button. 2. The merchant client-side sends the customer's purchase information to the merchant server-side, and the merchant server-side sends this information to Dojo server to [create a payment intent](https://docs.dojo.tech/plugins/woocommerce/introduction#step-3-create-a-payment-intent). 3. The merchant client-side creates an instance of the [card component](https://docs.dojo.tech/plugins/woocommerce/introduction#step-1-add-the-component-to-your-checkout-page) using the `clientSessionSecret`. 4. The customer enters payment details directly on the merchant checkout page to the card component. 5. The card component collects the customer's payment details, sends them to the Dojo servers, and redirects the customer to the result page. 6. The merchant server receives a [webhook notification](https://docs.dojo.tech/plugins/woocommerce/introduction#step-4-handle-post-payment-events) when the payment is completed. ![](https://docs.dojo.tech/images/flow-card.jpg) **Flow diagram: Flow Card** ```mermaid sequenceDiagram actor C as Customer participant MC as Merchant Client-side participant MS as Merchant Server-side participant D as dojo C->>MC: Clicks "Checkout" MC->>MS: Sends information about customer purchases MS->>D: POST /payment-intents D-->>MS: PaymentIntent object MS-->>MC: Returns clientSessionSecret C->>MC: Enters payment details and clicks "Pay" MC->>D: D-->>MC: Redirects to the result page D->>MS: Sends webhooks ``` > **Info:** If you’re looking for a low-code option, take a look at our [pre-built checkout](https://docs.dojo.tech/plugins/checkout-page). > ## How to process a payment Step-by-step guide: 1. [Add the component to your checkout page](https://docs.dojo.tech/plugins/woocommerce/introduction#step-1-add-the-component-to-your-checkout-page). 2. [Set up Dojo Card Component](https://docs.dojo.tech/plugins/woocommerce/introduction#step-2-set-up-dojo-card-component). 3. [Create a payment intent](https://docs.dojo.tech/plugins/woocommerce/introduction#step-3-create-a-payment-intent). 4. [Handle post-payment events](https://docs.dojo.tech/plugins/woocommerce/introduction#step-4-handle-post-payment-events). 5. [Test and go live](https://docs.dojo.tech/plugins/woocommerce/introduction#step-5-test-and-go-live). ### Before you start ### Step 1. Add the component to your checkout page Include Dojo `client.js` script on your checkout page. This script must always load directly from `cdn.dojo.tech` to remain PCI compliant—you can’t include it in a bundle or host a copy of it yourself. ```html title="index.html" ``` Add empty placeholders div to your checkout page to create a payment form. For example: ```html title="index.html" Card component Payment Complete
Status Code
Auth Code
``` ### Step 2. Set up Dojo card component Next, in your JavaScript file, create an instance of Dojo: ```js title="script.js" .then(response => response.json()) .then(function (data) { const config = { paymentDetails: { paymentToken: data.clientSessionSecret, }, containerId: "demo-payment", fontCss: ['https://fonts.googleapis.com/css?family=Do+Hyeon'], styles: { base: {}, } } // intialising connection const card = new Dojo.Payment(config, displayErrorsCallback); // sending payment on button click and processing the response const btnTestPay = document.getElementById("testPay"); btnTestPay.onclick = () => { btnTestPay.innerText = 'loading'; btnTestPay.setAttribute("disabled", "true"); card.executePayment() .then(function (data) { document.getElementById("demo-payment").hidden = true; btnTestPay.remove(); document.getElementById("demo-result").hidden = false; document.getElementById("status-code").innerText = data.statusCode; document.getElementById("auth-code").innerText = data.authCode; }).catch(function (data) { console.log('Payment Request failed: ' + data); btnTestPay.innerText = 'Pay'; btnTestPay.removeAttribute("disabled"); if (typeof data === 'string') { document.getElementById("errors").innerText = data; } if (data && data.message) { document.getElementById("errors").innerText = data.message; } } ); }; ``` You can add an optional callback to display validation errors, such as invalid CVV or card number: ```js title="script.js" function displayErrorsCallback(errors) { const errorsDiv = document.getElementById('errors'); errorsDiv.innerHTML = ''; if (errors && errors.length) { const list = document.createElement("ul"); for (const error of errors) { const item = document.createElement("li"); item.innerText = error.message; list.appendChild(item); } errorsDiv.appendChild(list); } } ``` See the [Optional configuration](https://docs.dojo.tech/plugins/woocommerce/configuration) for a complete list of parameters that you can use. ### Step 3. Create a payment intent Call a server-side endpoint to create a payment intent, for example: ```js title="script.js" fetch('/checkout', { // Declare what type of data we're sending headers: { 'Content-Type': 'application/json' }, // Specify the method method: 'POST', mode: 'no-cors', // A JSON payload body: JSON.stringify({ "greeting": "" }) }) ``` To create a payment intent, the following parameters are required: - `amount`: This includes the currency and value, in minor units, for example, "1000" for 10.00 GBP. - `reference`: Your unique reference for the payment intent. - `paymentMethods: "Card"`: The payment method that customers can use to pay. Here's an example of how to create a payment intent on your server-side: ```py title="server.py" payload = json.dumps({ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order 245", "paymentMethods": ["Card"] }) headers = { 'Content-Type': "application/json", 'Version': "2024-02-05", 'Authorization': "Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ" # <-- Change to your secret key } conn.request("POST", "/payment-intents/", payload, headers) # handling the response from POST res = conn.getresponse() data = res.read() resp_data = {} resp_data['clientSessionSecret'] = json.loads(data)["clientSessionSecret"] print(resp_data) json_data = json.dumps(resp_data) resp = app.response_class( response=json_data, mimetype='application/json' ) return resp ``` See the [API reference](https://docs.dojo.tech/api#operation/PaymentIntents_CreatePaymentIntent) for a complete list parameters that you can use. ### Step 4. Handle post-payment events ### Step 5. Test and go live Before going live, test your integration using the test card numbers: --- ## Next steps [![](https://docs.dojo.tech/images/dojo-icons/AnchorSimple.svg) **Set up notification webhooks** Use webhooks to receive updates related to your payments.](../../../../development-resources/webhooks) [![](https://docs.dojo.tech/images/dojo-icons/Settings.svg) **Configure Dojo Components** Find out how you can configure the Dojo Components.](./configuration) [![](https://docs.dojo.tech/images/dojo-icons/TickCircle.svg) **Check your integration** Check off these steps before launching your integration in production.](checklist) [![](https://docs.dojo.tech/images/dojo-icons/Filters.svg) **Manage payments** Learn how to capture or reverse payments, retrieve payment details or change payments amount.](../../../manage-payments) --- ## Go-live checklist(Components) > Check off these steps before launching your integration in production. The steps below will help to ensure you have a complete implementation. **Test in the sandbox** Before going live, test your integration in the [sandbox](https://docs.dojo.tech/development-resources/portal#sandbox-and-production-environments). For each payment method that you offer: * Make a successful payment. * Make an unsuccessful payment. * Make a successful payment after an unsuccessful one to test you [update a client session secret](https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_RefreshClientSessionSecret). * Make a successful payment with 3DS. * Make an unsuccessful payment with 3DS. Use the test card numbers below to make payments: **Update the client session secret** You need to [update the client session secret](https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_RefreshClientSessionSecret) every time you make any changes to the payment intent or the payment is declined. These tokens are **one-time use only**. If you need to retry a payment, you must generate a new token. Any changes to the payment intent amount invalidates the old client session secret and generates a new one. **Check the domain verification file** If you use the [wallet component](https://docs.dojo.tech/plugins/woocommerce/wallet) to enable Apple Pay, you must host the [domain verification file](https://cdn.dojo.tech/payments/assets/ApplePay/apple-developer-merchantid-domain-association) on each domain you want to use, including subdomains, under the following path: `https://yourdomain/.well-known/apple-developer-merchantid-domain-association`. Make sure that the file is downloadable and served at the correct location, as Apple will use this location to verify the validity of your domain. If your domain is protected from public access and you wish to complete domain verification, you should allow [Apple IP Addresses for Domain Verification](https://developer.apple.com/documentation/apple_pay_on_the_web/setting_up_your_server/#3179116). **Check the result** Make your first live API call to make sure that your production key is working. Open your checkout page to see the result. --- ## Dojo components >Learn how to use the Dojo Components for your online payments. Dojo Components are our ready-made JavaScript components that you can add to your website to accept payments. The components have error handling and input validation on the Client-side. > **Info:** If you’re looking for a low-code option, take a look at our [pre-built checkout](https://docs.dojo.tech/payments/accept-payments/online-payments/checkout-page). > ![](https://docs.dojo.tech/images/components.jpg) --- ## Ready to get started? [![](https://docs.dojo.tech/images/dojo-icons/PaymentCard.svg) **Card Component** Learn how to use our card component to accept payments.](/payments/accept-payments/online-payments/components/card) [![](https://docs.dojo.tech/images/dojo-icons/Wallet.svg) **Wallet Component** Learn how to use our single component for Apple Pay and Google Pay.](/payments/accept-payments/online-payments/components/wallet) --- ## Configure Dojo components ## Dojo Card ```js const card = new Dojo.Payment(config, displayErrorsCallback, onSubmitTriggered, onBlur); ``` | Parameter | Type | Description | |-------------------------|----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `config` | object [Config](https://docs.dojo.tech/plugins/woocommerce/introduction#configuration) | Required. Config containing details of this payment and the styling of the payment form. | | `displayErrorsCallback` | function | An optional callback to display text [validation errors](https://docs.dojo.tech/plugins/woocommerce/introduction#validation-error). The supplied function is called when there is a validation state change. This function is passed an array of validationError objects. | | `onSubmitTriggered` | function | An optional callback that's called when the submit event on the payment form is fired. This allows the payment to be submitted or extra validation done when the user presses the enter key on the payment form. | | `onBlur` | function(isValid: boolean) | An optional callback that's called when focus is lost from any field in the form. The parameter isValid will be true when all fields are completed and there are no validation errors. | ## Dojo Wallet ```js const wallet = new Dojo.WalletPayment(config, displayErrorsCallback, paymentComplete); ``` | Parameter | Type | Description | |-----|-----|-----| |`config` |object [Config](https://docs.dojo.tech/plugins/woocommerce/introduction#configuration)|Required. Config containing details of this payment and the styling of the payment button. | |`displayErrorsCallback` |function| An optional callback to display text [validation errors](https://docs.dojo.tech/plugins/woocommerce/introduction#validation-error). The supplied function is called when there is a validation state change. This function is passed an array of validationError objects.| |`paymentComplete` | function|A callback that returns the result of payment. The supplied function is called when the payment is executed. This function is passed a [Transaction Result](https://docs.dojo.tech/plugins/woocommerce/introduction#transaction-result) object.| ## Configuration | Property | Type | Description | Card Component | Wallet Component | |---------------------------|----------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------|----------------|------------------| | `containerId` | string | Required. The id of the div element where the payment details will be displayed. | ✓ | ✓ | | `paymentDetails` | [paymentDetails](https://docs.dojo.tech/plugins/woocommerce/introduction#payment-details) | Required. Details of the payment to be made. | ✓ | ✓ | | `fontCss` | array of strings | Array of urls pointing to css files for importing fonts, for example `https://fonts.googleapis.com/css?family=Do+Hyeon` | ✓ | - | | `styles` | [stylesConfig](https://docs.dojo.tech/plugins/woocommerce/introduction#styles-configuration) | Required. Object defining custom styles for the payment form. | ✓ | - | | `text` | [textConfig](https://docs.dojo.tech/plugins/woocommerce/introduction#text-configuration) | Object defining text to override the defaults. | ✓ | - | | `onIframeLoaded` | function | An optional function that's called once the iframe has been loaded and configured. | ✓ | ✓ | | `onIframeLoadFailed` | function | An optional function that's called if there is an error loading the iframe. | ✓ | ✓ | | `errorMessages` | [errorMessages](https://docs.dojo.tech/plugins/woocommerce/introduction#error-messages) | Object defining custom validation error messages for the payment form. | ✓ | ✓ | | `callbacks` | [callbacksConfig](https://docs.dojo.tech/plugins/woocommerce/introduction#card-callbacks) | Object defining callback functions on various events. | ✓ | - | | `callbacks` | [walletPaymentCallbacksConfig](https://docs.dojo.tech/plugins/woocommerce/introduction#wallet-callbacks) | Object defining callback functions on various events. | - | ✓ | | `buttonConfig` | [buttonConfig](https://docs.dojo.tech/plugins/woocommerce/introduction#button-configuration) | An optional button config. It defaults to colour black and type plain. | - | ✓ | | `emailRequired` | boolean | An optional config to collect the buyer's email. It defaults to false. | - | ✓ | | `billingAddressRequired` | boolean | An optional config to collect the buyer's billing address. It defaults to false. | - | ✓ | | `shippingAddressRequired` | boolean | An optional config to collect the buyer's shipping address. It defaults to false. | - | ✓ | ### Payment details | Property | Type | Description | |----------------|--------|------------------------------------------------------------------| | `paymentToken` | string | Required. The access token supplied by the get access token API. | ### Styles configuration | Property | Type | Description | |--------------|--------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------| | `base` | [fieldStyle](https://docs.dojo.tech/plugins/woocommerce/introduction#field-style) | Required. Styles to be applied to all fields. | | `cv2` | [fieldStyle](https://docs.dojo.tech/plugins/woocommerce/introduction#field-style) | Styles to override the base styles for the cv2 field. | | `cardNumber` | [fieldStyle](https://docs.dojo.tech/plugins/woocommerce/introduction#field-style) | Styles to override the base styles for the card number field. | | `expiryDate` | [fieldStyle](https://docs.dojo.tech/plugins/woocommerce/introduction#field-style) | Styles to override the base styles for the expiry date field. | | `cardName` | [fieldStyle](https://docs.dojo.tech/plugins/woocommerce/introduction#field-style) | Styles to override the base styles for the card name field. | | `cardIcon` | [JavaScript CSS properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Properties_Reference) | Styles to be applied to the card icon. | | `form` | [JavaScript CSS properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Properties_Reference) | Styles to be applied HTML form element containing all the fields. | #### Field style | Property | Type | Description | |------------------|--------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------| | `default` | [JavaScript CSS properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Properties_Reference) | Styles to be applied when the field is in its initial state. | | `focus` | [JavaScript CSS properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Properties_Reference) | Styles to be applied when the field has focus. | | `error` | [JavaScript CSS properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Properties_Reference) | Styles to be applied when the field has failed validation. | | `valid` | [JavaScript CSS properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Properties_Reference) | Styles to be applied when the field has passed validation. | | `errorFocus` | [JavaScript CSS properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Properties_Reference) | Styles to be applied when the field has focus and is in an error state. | | `validFocus` | [JavaScript CSS properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Properties_Reference) | Styles to be applied when the field has focus and is valid. | | `container` | [JavaScript CSS properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Properties_Reference) | Styles to be applied to the div wrapping the label and the input field. | | `label` | [JavaScript CSS properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Properties_Reference) | Styles to be applied to the label. | | `validationText` | [JavaScript CSS properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Properties_Reference) | Styles to be applied to the validation message. Only applicable if `text.(cardName \|cardNumber\|expiryDate\|cv2).showValidation` is `true`.| | `validationIcon` | [JavaScript CSS properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Properties_Reference) | Styles to be applied to the validation message icon. Only applicable if `text.(cardName \|cardNumber\|expiryDate\|cv2).showValidation` is `true`. E.g., to set the icon colour to purple set this property to `{ backgroundColor: 'purple' }`| ### Text configuration | Property | Type | Description | |--------------|--------------------------|------------------------------------------------------------------------| | `cardName` | [fieldText](https://docs.dojo.tech/plugins/woocommerce/introduction#field-text) | Config to override the default card name placeholder and label text. | | `cardNumber` | [fieldText](https://docs.dojo.tech/plugins/woocommerce/introduction#field-text) | Config to override the default card number placeholder and label text. | | `expiryDate` | [fieldText](https://docs.dojo.tech/plugins/woocommerce/introduction#field-text) | Config to override the default cv2 placeholder and label text. | | `cv2` | [fieldText](https://docs.dojo.tech/plugins/woocommerce/introduction#field-text) | Config to override the default expiry date placeholder and label text. | #### Field text | Property | Type | Description | |------------------|---------|---------------------------------------------------------------------------------| | `label` | string | Required. Text to replace the default label text. | | `placeholder` | string | Required. Text to replace the default placeholder text. (Empty will be ignored) | | `showValidation` | boolean | Option to show the validation message. Defaults to false if not set. | ### Button configuration | Property | Type | Description | |----------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `colour` | string | It defaults to black, but it can optionally be changed to white. | | `type` | string | It defaults to plain (payment button without additional text), but it can optionally be changed to book (Book with GooglePay/ApplePay), buy, checkout, donate or order. | ### Error messages This allows overriding of the default error messages. This will override both the messages passed to displayErrorsCallback and the message displayed if showValidation is set to true. | Property | Type | Description | |----------------------------|--------|------------------------------------------------------------------------| | `cardNameRequired` | string | Card name isn't entered. | | `cardNameInvalid` | string | Invalid card name is entered. | | `cardNumberRequired` | string | Card number isn't entered. | | `cardNumberInvalid` | string | Invalid card number is entered. | | `expiryDateRequired` | string | Card expiry date isn't entered. | | `expiryDateInvalid` | string | Invalid card expiry date is entered. | | `expiryDateMustBeInFuture` | string | Card expiry date isn't in the future. | | `cv2Required` | string | [CV2](https://en.wikipedia.org/wiki/Card_security_code) isn't entered. | | `cv2Invalid` | string | Invalid CV2 is entered. | ### Card callbacks | Property | Type | Description | |--------------------|-----------------------------|------------------------------------------------------------------------------------------------| | `onFormComplete` | function | An optional function which is called once the form is complete and all input values are valid. | | `onFormFieldValid` | function(fieldName: string) | An optional function which is called once a form field input is valid. | ### Wallet callbacks | Property | Type | Description | |----------------------|----------|-------------------------------------------------------------------------------------------------| | `onPaymentCancelled` | function | An optional function which is called if the user closes the wallet payment form without paying. | | `onPaymentInitiated` | function | An optional function which is called when the wallet payment button is clicked. | ## Validation error | Property | Type | Description | |-------------|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `errorType` | string | The type of validation error that has occured. For the card component this can be one of the following: `cardNameRequired`, `cardNameInvalid`, `cardNumberRequired`, `cardNumberInvalid`, `expiryDateRequired`, `expiryDateInvalid`, `expiryDateMustBeInFuture`, `cv2Required`, or `cv2Invalid`. | | `message` | string | Message detailing the validation error for displaying to the user. | ## Execute payment ```js card.executePayment(additionalInfo) .then(function(data){ /*handle response here*/ }).catch(function(data){ /*handle failure here*/ } ``` When the promise is fulfilled the following object will be passed. ## Transaction result | Property | Type | Description | |--------------|----------------------------|---------------------------------------------------------------------------| | `statusCode` | [statusCode](https://docs.dojo.tech/plugins/woocommerce/introduction#status-code) | Indicated the status of the transaction. 0 for a successful transaction. | | `authCode` | string | If the transaction was successful, then the auth code is passed out here. | | `message` | string | This gives a more detailed description of the status of the transaction. | ### Status code | Status Code | Result | Description | |-------------|--------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `0` | Successful | The transaction was successful. | | `3` | Authorizing | The card holder hasn't completed 3DS, this status will only be seen on the REST API. | | `4` | Referred | The card issuer has parked the transaction awaiting contact with the customer before proceeding to authorize or decline the transaction. | | `5` | Declined | The transaction was declined by the card issuer or acquiring bank. | | `20` | Duplicate Transaction | The transaction which was processed was a duplicate. Ensure each transaction has a unique OrderId. | | `30` | Failed | Error executing transaction. | | `400` | Invalid Request | The request has failed validation by our servers and the transaction hasn't been submitted to the gateway. Possible causes for this are invalid transaction type or other data in the request. | | `401` | Issue with Access Token | The access token being used isn't valid, the transaction hasn't been submitted to the gateway. This can be caused if the token has already been used or the 30 minute expiry time has elapsed. | | `404` | No Access Token Supplied | No access token has been supplied to Connect-E. Transaction hasn't been submitted to the gateway. | | `500` | Internal Server Error | There's been an error submitting the transaction, please check the REST API for the status of the transaction. | ## Additional information The user's email address and billing address can be passed as the optional additionalInfo object as defined below. These values will override those set when the access token was created. | Property | Type | Description | |--------------------|-------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `userEmailAddress` | string | This email will be checked with the card issuer to provide additional security. | | `userPhoneNumber` | string | The cardholder's phone number. | | `billingAddress` | [address](https://docs.dojo.tech/plugins/woocommerce/introduction#address) | This address will be checked with the card issuer to provide additional security. | | `shippingDetails` | [shippingDetails](https://docs.dojo.tech/plugins/woocommerce/introduction#shipping-details) | Shipping details for the order. | | `metaData` | `Map` | Meta data to be passed at execution time. This will be merged into MetaData passed via the REST API. This can be represented as a JSON object with only string values, other types aren't supported. | ## Shipping details | Property | Type | Description | |-----------|---------------------|------------------------------------| | `name` | string | Name order is being shipped to. | | `address` | [address](https://docs.dojo.tech/plugins/woocommerce/introduction#address) | Address order is being shipped to. | ## Address | Property | Type | Description | |---------------|--------|-------------------------------------------------------------------------------------------| | `address1` | string | Customer’s billing address line 1. | | `address2` | string | Customer’s billing address line 2. | | `address3` | string | Customer’s billing address line 3. | | `address4` | string | Customer’s billing address line 4. | | `city` | string | Customer’s billing address city. | | `state` | string | Customer’s billing address state or county. | | `postcode` | string | Customer’s billing address postcode or zipcode. | | `countryCode` | string | Customer’s billing address country code using ISO 3166–1 for example United Kingdom: 826. | --- ## Wallet >Learn how you can embed our prebuilt wallet component on your checkout page. The Dojo Wallet Component is a prebuilt JavaScript component for accepting payments on your checkout page. Use this integration option when you want full control over the payment flow and the look of your checkout page. In terms of implementation, integration contains: - Server-side: one API request to create a payment intent. - Client-side: set up the Dojo Wallet Component, which securely sends payment data to our server. - Webhooks: server-side endpoint to receive information about the payment. The payment flow is: 1. The customer visits the merchant's site and clicks the **Checkout** button. 2. The merchant client-side sends the customer's purchase information to the merchant server-side, and the merchant server-side sends this information to the Dojo server to [create a payment intent](https://docs.dojo.tech/plugins/woocommerce/introduction#step-3-create-a-payment-intent). 3. The merchant client-side creates an instance of the [wallet component](https://docs.dojo.tech/plugins/woocommerce/introduction#step-1-add-the-component-to-your-checkout-page) using the `clientSessionSecret`. 4. The wallet component collects the customer's payment details, sends them to Dojo servers, and redirects the customer to the result page. 5. The merchant server receives a [webhook notification](https://docs.dojo.tech/plugins/woocommerce/introduction#step-4-handle-post-payment-events) when the payment is completed. ![](https://docs.dojo.tech/images/flow-wallet.jpg) **Flow diagram: Flow Wallet** ```mermaid sequenceDiagram actor C as Customer participant MC as Merchant Client-side participant MS as Merchant Server-side participant D as dojo C->>MC: Clicks "Checkout" MC->>MS: Sends information about customer purchases MS->>D: POST /payment-intents D-->>MS: PaymentIntent object MS-->>MC: Returns clientSessionSecret C->>D: Enters payment details and clicks "Pay" D-->>MC: Redirects to the result page D->>MS: Sends webhooks ``` > **Info:** If you’re looking for a low-code option, take a look at our [pre-built checkout](https://docs.dojo.tech/plugins/checkout-page). > ## How to process a payment Step-by-step guide: 1. [Add the component to your checkout page](https://docs.dojo.tech/plugins/woocommerce/introduction#step-1-add-the-component-to-your-checkout-page). 2. [Set up Dojo Wallet Component](https://docs.dojo.tech/plugins/woocommerce/introduction#step-2-set-up-dojo-wallet-component). 3. [Create a payment intent](https://docs.dojo.tech/plugins/woocommerce/introduction#step-3-create-a-payment-intent). 4. [Handle post-payment events](https://docs.dojo.tech/plugins/woocommerce/introduction#step-4-handle-post-payment-events). 5. [Test and go live](https://docs.dojo.tech/plugins/woocommerce/introduction#step-5-test-and-go-live). ### Before you start To enable Apple Pay, you must host the [domain verification file](https://cdn.dojo.tech/payments/assets/ApplePay/apple-developer-merchantid-domain-association) on each domain you want to use, including subdomains, under the following path: `https://yourdomain/.well-known/apple-developer-merchantid-domain-association`. Make sure that the file is downloadable and served at the correct location, as Apple will use this location to verify the validity of your domain. If your domain is protected from public access, and you wish to complete domain verification, you should allow [Apple IP Addresses for Domain Verification](https://developer.apple.com/documentation/apple_pay_on_the_web/setting_up_your_server/#3179116). #### Terms and Conditions - By integrating Apple Pay, you adhere to the [Apple Pay APIs Acceptable Use Policy](https://developer.apple.com/apple-pay/acceptable-use-guidelines-for-websites/) and accept the terms and conditions defined in the [Apple Pay Web Merchant Terms and Conditions](https://developer.apple.com/apple-pay/terms/apple-pay-web/). - By integrating Google Pay, you adhere to the [Google Pay APIs Acceptable Use Policy](https://payments.developers.google.com/terms/aup) and accept the terms defined in the [Google Pay API Terms of Service](https://payments.developers.google.com/terms/sellertos). ### Step 1. Add the component to your checkout page Include the Dojo `client.js` script in your checkout page. This script must always load directly from `cdn.dojo.tech` to remain PCI-compliant. You can’t include it in a bundle or host a copy of it yourself. ```html title="index.html" ``` Add empty a placeholder `div` to your checkout page to create a payment form. For example: ```html title="index.html" Wallet component Payment Complete
Status Code
Auth Code
Message
``` ### Step 2. Set up Dojo Wallet Component Next, in your JavaScript file, create an instance of Dojo: ```js title="script.js" .then(response => response.json()) .then(function (data) { const config = { containerId: 'demo-payment-wallet', paymentDetails: { paymentToken: data.clientSessionSecret, }, buttonConfig: { color: 'black', type: 'plain' }, emailRequired: true, billingAddressRequired: false, shippingAddressRequired: false } const wallet = new Dojo.WalletPayment(config, displayErrorsCallback, paymentComplete); function paymentComplete(response) { document.getElementById('demo-payment-wallet').hidden = true; document.getElementById('demo-result').hidden = false; document.getElementById('status-code').innerText = response.statusCode; document.getElementById('auth-code').innerText = response.authCode; document.getElementById('message').innerText = response.message; } ``` See the [optional configuration](https://docs.dojo.tech/plugins/woocommerce/configuration) for a complete list of parameters that you can use. ### Step 3. Create a payment intent Call a server-side endpoint to create a payment intent, for example: ```js title="script.js" fetch('/checkout', { // Declare what type of data we're sending headers: { 'Content-Type': 'application/json' }, // Specify the method method: 'POST', mode: 'no-cors', // A JSON payload body: JSON.stringify({ "greeting": "" }) }) ``` To create a payment intent, the following parameters are required: - `amount`: This includes the currency and value, in minor units, for example, "1000" for 10.00 GBP. - `reference`: Your unique reference for the payment intent. - `paymentMethods: "Wallet"`: The payment method that customers can use to pay. Here's an example of how to create a payment intent on your server-side: ```py title="server.py" # call post payment-intent payload = json.dumps({ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order 245", "paymentMethods": ["Wallet"] }) headers = { 'Content-Type': "application/json", 'Version': "2024-02-05", 'Authorization': "Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ" # <-- Change to your secret key } conn.request("POST", "/payment-intents/", payload, headers) # handling the response from POST res = conn.getresponse() data = res.read() resp_data = {} resp_data['clientSessionSecret'] = json.loads(data)["clientSessionSecret"] print(resp_data) json_data = json.dumps(resp_data) resp = app.response_class( response=json_data, mimetype='application/json' ) return resp ``` See the [API reference](https://docs.dojo.tech/api#operation/PaymentIntents_CreatePaymentIntent) for a complete list parameters that you can use. ### Step 4. Handle post-payment events ### Step 5. Test and go live Before going live, test your integration. #### Testing Apple Pay To enable test cards for Apple Pay, you must have an Apple Sandbox Tester Account, then you will be able to add test cards into your Apple Wallet. See [Apple's Sandbox Testing Documentation](https://developer.apple.com/apple-pay/sandbox-testing/) to setup your Sandbox Tester Account and check the section Test Cards for Apps and the Web to see the full list of supported test cards by Apple. Although our test payment gateway doesn't support all of them, so if you want to test successful cases, please use the cards listed in the Test Cards section. If you aren't enrolled into the Apple Developer Program and need a tester account, please contact our support team for further instructions. #### Testing Google Pay The Google Pay [Test Card Suite](https://developers.google.com/pay/api/android/guides/resources/test-card-suite) allows you to test Google Pay without the need of adding real cards to Google accounts. To instantly view these cards in your Google Account TEST environment, join [Google's User Group](https://groups.google.com/g/googlepay-test-mode-stub-data). All test cards will be automatically added to your account. --- ## Next steps [![](https://docs.dojo.tech/images/dojo-icons/AnchorSimple.svg) **Set up notification webhooks** Use webhooks to receive updates on your payments.](../../../../development-resources/webhooks) [![](https://docs.dojo.tech/images/dojo-icons/Settings.svg) **Configure Dojo Components** Find out how you can configure Dojo's components.](./configuration) [![](https://docs.dojo.tech/images/dojo-icons/TickCircle.svg) **Check your integration** Check off these steps before launching your integration in production.](checklist) [![](https://docs.dojo.tech/images/dojo-icons/Filters.svg) **Manage payments** Learn how to capture or reverse payments, retrieve payment details, or change payment amount.](../../../manage-payments) --- ## Go-live checklist(Payment-links) > Check off these steps before launching your integration in production. The steps below will help to ensure you have a complete implementation. **Test in the sandbox** Before going live, test your integration in the [sandbox](https://docs.dojo.tech/development-resources/portal#sandbox-and-production-environments). For each payment method that you offer: * Make a successful payment. * Make an unsuccessful payment. Use the test card numbers below to make payments: **Check the result** Make your first live API call to make sure that your production key is working. Follow the payment link you generated to see the result. For the production environment, there should be no yellow label **Sandbox**. --- ## Payment links >Embed or share a link to the [Dojo Prebuilt Checkout](https://docs.dojo.tech/payments/accept-payments/online-payments/checkout-page), to start accepting payments anytime, anywhere. Payment links are a quick and simple way to accept payments from customers without needing a full website. Payments links provide complete flexibility for customers to pay across devices. To complete payment, each customer is issued with a unique link which will direct them to Dojo's secure checkout page. This checkout page is completely customizable, so you can design a checkout flow to fit your brand. You can create a payment link via the Dojo customer app or directly using the Dojo Payments API. If you are using the app, you can generate new links with no coding required. Simply generate a new link each time you wish to create an order. You can also automate the process using the Payments API, but some developer configuration will be required to set this up. Payment links expire after thirty days, and each link can only be used once. After a customer makes a successful payment, anyone else accessing that payment link in the future will see a "Payment successful" message. You can track any payment within the Dojo customer app. Once paid, you’ll see the funds in your next transfer. ![](https://docs.dojo.tech/images/payment-links.jpg) --- ## Ready to get started? [![](https://docs.dojo.tech/images/dojo-icons/MobileInformation.svg) **Dojo App** Create each payment link manually using Dojo App.](https://support.dojo.tech/hc/en-gb/articles/4415821097874-How-to-use-payment-links) [![](https://docs.dojo.tech/images/dojo-icons/BookBookmark.svg) **API step-by-step guide** Generate payment links automatically through the API.](/payments/accept-payments/online-payments/payment-links/step-by-step-guide) {/*Follow this style of linking*/} --- ## Step-by-step guide(Payment-links) >Learn how to generate payment links automatically through the API. In terms of implementation, the integration contains: - Server-side: one API request to create a payment intent. - WebHooks: at least one server-side endpoint, to receive information about the payment. The payment flow is: 1. The merchant server-side sends the payment information to the Dojo server to [create a payment intent](https://docs.dojo.tech/plugins/woocommerce/introduction#step-1-create-a-payment-link). 2. The merchant server-side generates a payment link and [sends it to the customer](https://docs.dojo.tech/plugins/woocommerce/introduction#step-2-send-the-payment-link-to-your-customer). 3. The customer opens the payment link, and they are redirected to the [Prebuilt Checkout Page](https://docs.dojo.tech/plugins/checkout-page). This is hosted by Dojo. 4. The Prebuilt Checkout Page collects the customer's payment details and sends them to Dojo servers, then redirects the customer to the result page. 5. The merchant server receives a [WebHook notification](https://docs.dojo.tech/plugins/woocommerce/introduction#step-3-handle-post-payment-events) when the customer uses the payment link. ![](https://docs.dojo.tech/images/flow-payment-links.jpg) **Flow diagram: Flow Payment Links** ```mermaid sequenceDiagram actor C as Customer participant DC as dojo Client-side participant MS as Merchant Server-side participant DS as dojo Server-side C->>MS: Requests Payment Link MS->>DS: POST /payment-intents (paymentSource: "payment-links") DS-->>MS: PaymentIntent object MS-->>C: Sends Payment Link C->>DC: Opens Payment Link C->>DC: Enters payment details and clicks "Pay" DS-->>DC: Redirects to the result page DS->>MS: Sends webhooks ``` ## How to process a payment Step-by-step guide: 1. [Create a payment link](https://docs.dojo.tech/plugins/woocommerce/introduction#step-1-create-a-payment-link). 2. [Send the payment link to your customer](https://docs.dojo.tech/plugins/woocommerce/introduction#step-2-send-the-payment-link-to-your-customer). 3. [Handle post-payment events](https://docs.dojo.tech/plugins/woocommerce/introduction#step-3-handle-post-payment-events). 4. [Test and go live](https://docs.dojo.tech/plugins/woocommerce/introduction#step-4-test-and-go-live). ### Before you start ### Step 1. Create a payment link To create a payment link, first call a server-side endpoint to create a payment intent. The following parameters are required: - `amount`: This includes the currency and value, in minor units, for example, "1000" for 10.00 GBP. - `reference`: Your unique reference for the payment intent. - `isNotOnlineCheckout`: Set to true to start accepting payment links without an online checkout integration. Defaults to false if omitted. Requires a verified partner integration for use in production. Here's an example of how to create a payment intent for 10 GBP on your server-side: ```py title="server.py" @app.route('/', methods=['GET', 'POST']) def hello(): print(request.get_json()) # parse as JSON conn = http.client.HTTPSConnection("api.dojo.tech") payload = json.dumps({ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order 245", }) headers = { 'Content-Type': "application/json", 'Version': "2024-02-05", 'Authorization': "Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ" # <-- Change to your secret key } conn.request("POST", "/payment-intents/", payload, headers) res = conn.getresponse() data = res.read() last_id = json.loads(data)["id"] url = 'https://pay.dojo.tech/checkout/' + last_id return redirect(url) ``` See the [API reference](https://docs.dojo.tech/api#operation/PaymentIntents_CreatePaymentIntent) for a complete list of parameters that can be used for payment intent creation. ### Step 2. Send the payment link to your customer After receiving the request, Dojo creates a payment intent and returns its unique ID: ```json { "id": "pi_sandbox_RBMHTJ4fIkmSppDILZVCGw", ... } ``` Return this ID to the client-side and use it to create a link in the following format: `https://pay.dojo.tech/checkout/{{id}}` Send the link to your customer through chat or email. When the customer opens the link, they'll redirect to Dojo Prebuilt Checkout Page. After the customer fills in their payment information, Dojo processes the payment and redirects the customer to the success page. ### Step 3. Handle post-payment events ### Step 4. Test and go live Before going live, test your integration using the test card numbers: --- ## Next steps [![](https://docs.dojo.tech/images/dojo-icons/AnchorSimple.svg) **Set up notification WebHook** Use WebHooks to receive updates related to your payments.](../../../../development-resources/webhooks) [![](https://docs.dojo.tech/images/dojo-icons/Settings.svg) **Configure Dojo Checkout Page** Find out how to add another payment method or shipping address form to the page.](../checkout-page/configuration) [![](https://docs.dojo.tech/images/dojo-icons/TickCircle.svg) **Check your integration** Check off these steps before launching your integration in production.](checklist) [![](https://docs.dojo.tech/images/dojo-icons/Filters.svg) **Manage payments** Learn how to capture or reverse payments, retrieve payment details or change payments amount.](../../../manage-payments) --- ## Go-live checklist(Virtual-terminal) > Check off these steps before launching your integration in production. The following steps ensure you have a complete implementation. **Ensure that your business is PCI-compliant.** You must submit the [Self-Assessment Questionnaire A](https://listings.pcisecuritystandards.org/documents/PCI-DSS-v3_2-SAQ-C_VT-rev1_1.pdf) to [Dojo](https://support.dojo.tech/hc/en-gb). **Contact Dojo to enable Virtual Terminal (VT) payments** As a Dojo customer, if your business is enabled for card-not-present (CNP) payments, you can set up your own virtual terminal with Dojo. To enable a virtual terminal in your account, contact [Dojo customer support](https://support.dojo.tech/hc/en-gb). **Ensure that your VT implementation is ready** You must have either a [prebuilt checkout page](https://docs.dojo.tech/plugins/checkout-page) or a [checkout component](https://docs.dojo.tech/plugins/components) ready alongside your complete VT implementation to start accepting payments. **Test in the sandbox** Before going live, test your integration in the [sandbox](https://docs.dojo.tech/development-resources/portal#sandbox-and-production-environments). For each payment method that you offer: * Make a successful payment. * Make an unsuccessful payment. Use the test card numbers below to make payments: > **Note:** When using a test card with [3D security (3DS)](https://en.wikipedia.org/wiki/3-D_Secure), the virtual terminal will automatically skip all 3DS checks. > > > > > > > > > > > > > > > > > > > **Check the result** > > Make your first live API call to make sure that your production key is working. > Follow the payment link you generated to see the result. > For the production environment, there should be no yellow **Sandbox** label. > > > --- > > ## Securing VT transactions > > > Learn about securing virtual terminal transactions for your business. > > To ensure that your virtual terminal transactions are secure, you must understand the following: > > - **Limited authentication**: Virtual terminal transactions don’t require authentication, as their transactions take place over a phone call, email, or mail order. To enhance your security, you can add an [Address Verification Service (AVS)](https://en.wikipedia.org/wiki/Address_verification_service) check to your payment process. > > - **Understand chargebacks**: Chargebacks occur when customers dispute a transaction and request a refund from their issuing bank. Virtual terminals are prone to a high risk of chargebacks when compared to Payment Links. Ensure you implement [Strong Customer Authentication (SCA)](https://www.fca.org.uk/firms/strong-customer-authentication) to minimize chargebacks. > > - **Data breaches**: Virtual terminal transactions often involve the exchange of sensitive information, such as credit card details, personal data, and transaction history. By implementing robust security measures, securing your payment systems, and staying updated on the latest security practices, you can help prevent data breaches and protect your customers' confidential information. > > - **PCI compliance**: PCI sets strict security standards for handling cardholder data, to protect against unauthorized access. To minimize risk, your business must be PCI-compliant. > > --- > > ## Step-by-step guide(Virtual-terminal) > > Step-by-step guide to set up your own virtual terminal. > > ## Setup flow > > To set up a virtual terminal for your web app, do the following: > > **Info:** - This guide assumes that you are setting up your virtual terminal using Dojo’s [prebuilt checkout page](https://docs.dojo.tech/plugins/checkout-page). Similarly, you can set up a virtual terminal with [components](https://docs.dojo.tech/plugins/components) and [mobile integration](https://docs.dojo.tech/mobile-integration). ![](https://docs.dojo.tech/images/virtual-terminal.png) ## Step 1. Create a payment intent To create a payment intent, call a server-side endpoint. For that, the following parameters are required: - `amount`: This includes the currency and value, in minor units, for example, "1000" for 10.00 GBP. - `reference`: Your unique reference for the payment intent. - `cardHolderNotPresent: "true"`: Confirms that the card holder is not present during the transaction. > **Info:** - When `cardHolderNotPresent` is set to `true`, it means payments are made through the mail or over the telephone. They are a common use case for virtual terminals. > - To process these transactions, you must have a virtual terminal to accept payments over the phone, fax, email, or by mail. This type of transaction is common for businesses that operate remotely or have a significant online presence. > - Using `cardHolderNotPresent`, you can implement a virtual terminal in [components](https://docs.dojo.tech/plugins/components) and [Mobile integration](https://docs.dojo.tech/mobile-integration). Here's an example of how to create a virtual terminal payment for 10 GBP: ```bash # The sandbox API key passed in 'authorization' is public. # Don’t submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents \ --header 'content-type: application/json' \ --header 'authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'version: 2022-07-04' \ --data '{ "amount":{ "value":1000, "currencyCode":"GBP" }, "reference":"Order 234", "cardHolderNotPresent": true }' ``` ## Step 2. Redirect to Dojo Checkout Page 1. After receiving the request, Dojo creates a payment intent and returns its unique ID: ```json { "id": "pi_sandbox_RBMHTJ4fIkmSppDILZVCGw", ... } ``` 2. Return this `id` to the client-side and use it to create a link in the following format: `https://pay.dojo.tech/checkout/{{id}}` 3. Share the link with your merchant. Clicking this link will render the checkout page at the merchant's end. :::warning Do not share this link with your customer. This link is for the **merchant use only**. ## Step 3. Request card details from the customer Next, the merchant requests card details from the customer over a call, email, or mail order. When the customer authorizes the merchant to make the payment, the merchant fills in the customer's card details on the checkout page. Dojo processes the payment and redirects to the success page. Finally, the customer is notified via email about the successful payment. ### Step 4. Handle post-payment events ### Step 5. Test and go live Before going live, test your integration using the test card numbers: --- --- ## Virtual terminal >Learn about accepting payments using a virtual terminal. A virtual terminal is an online interface that allows merchants to process payments without needing a physical card terminal. Virtual terminals are one of the ways you can handle [Card Not Present (CNP)](https://dojo.tech/articles/what-is-card-not-present/) payments. They enable you to securely process phone or mail orders using your computer or mobile device, without the need for a customer - or a physical card terminal - to be physically present. Virtual terminals are especially beneficial for remote businesses, such as service-based companies, and mobile businesses. With a virtual terminal, businesses can accept payments from any device with an internet connection. This flexibility is crucial for businesses looking to expand their customer base and provide a convenient payment option for their customers. > **Note:** Because the cardholder is present on the phone, you _can_ use Dojo’s virtual terminal to accept payments instantly. However, Dojo recommends [payment links](https://docs.dojo.tech/payments/accept-payments/online-payments/payment-links) as the most secure method for accepting CNP payments. > > > ## Can I set up a virtual terminal with Dojo? > > As a Dojo customer, if your business is enabled for CNP payments, you can set up your own virtual terminal. Contact [Dojo customer support](https://support.dojo.tech/hc/en-gb) for details. > > --- > > ## Ready to get started? > > > > [![](https://docs.dojo.tech/images/dojo-icons/MobileInformation.svg) **Dojo App** Accept payments with virtual terminal in your Dojo for Business app.](https://support.dojo.tech/hc/en-gb/articles/7949437308828-Take-remote-payments-with-the-virtual-terminal) > > [![](https://docs.dojo.tech/images/dojo-icons/BookBookmark.svg) **API step-by-step guide** Accept payments with your own virtual terminal using the API.](virtual-terminal/step-by-step-guide) > > > > --- > > ## Virtual terminal vs Payment links > > Know how Virtual Terminals are different from Payment Links. > > Virtual Terminals and [Payment Links](https://docs.dojo.tech/plugins/payment-links) have some similarities but a number of key differences. > > | Feature | Virtual terminal | Payment links | > |---------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| > | **Payment process flow** | Card details are entered by the merchant when the customer provides their credit card details over the phone, or through a mail order. The merchant enters these details into their payment terminal or e-commerce platform to process the transaction. | Card details are entered by the customer where the merchant generates a unique link for a specific amount and sends it to the customer via email, SMS, or other messaging platforms. The customer clicks on the link and is redirected to a secure page where they can enter their card details and complete the transaction. | > | **Security measures** | The risk of fraud in virtual terminals is relatively higher as the merchant manually inputs the card details received from the customer, making this method less secure. | This method is safer as the customer enters their own card details. These transactions require strong customer authentication (SCA), that is, [3DS 2.0](https://3dsecure2.com/), reducing the risk of fraud. | > | **Customer experience** | Virtual terminal payments can be less convenient for some customers, as this method requires direct interaction with the merchant. | Payment links are often considered more convenient, as the customer can pay at any time and on any device. The customer may not need to interact directly with the merchant to complete the payment. | > | **Merchant experience** | Virtual terminal payments can be more labor-intensive for the merchant, as they are required to manually input card details and handle sensitive customer information. | Payment links can be generated with minimal effort. The merchant does not need to handle sensitive card information. | > | **Industry applications** | Any small or large business that does not provide an online payment option. | Any business looking to simplify the payment process and improve customer experience with pay-by-link. | > > **Note:** Dojo recommends that you use payment links over virtual terminals as a more secure method for accepting payments. --- ## Cancel a payment >Find out how to cancel a payment intent that hasn't yet been authorized. Payment intents can be canceled if they are no longer needed — for instance, if the card issuer declines authorization. Note that cancellation is only possible while the intent is in the Created status ## Cancel using the Dojo API To cancel a payment to your customer, use the endpoint below: > See OpenAPI spec for DELETE endpoint details: https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_Delete In your request, include: * `paymentIntentId`: identifies the payment being canceled. For the full specification, see the [API reference](https://docs.dojo.tech/api#operation/PaymentIntents_Delete). ### Request example The next example shows how to cancel a payment intent. ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request DELETE \ --url https://api.dojo.tech/payment-intents/ \ --header 'Authorization: Basic ' \ --header 'Version: 2024-02-05' ``` ### Response example If your request is successful, the response will return information about the canceled payment, and the status will be `Canceled`. ```json { "id": "pi_sandbox_RBMHTJ4fIkmSppDILZVCGw", "captureMode": "Auto", "status": "Canceled", "paymentMethods": [ "Card" ], "amount": { "value": 1000, "currencyCode": "GBP" }, "totalAmount": { "value": 1000, "currencyCode": "GBP" }, "createdAt": "2022-02-21T14:39:21.6050276Z", "updatedAt": "2022-02-21T14:39:21.6050277Z" } ``` --- ## Cancelling payments >Learn how to reverse, refund or cancel a payment with the Dojo Payments API. For a detailed integration guide, select an option below: [![](https://docs.dojo.tech/images/dojo-icons/Close.svg) **Cancel** Find out how to cancel a payment that hasn't yet been authorized.](/payments/manage-payments/cancelling-payments/cancel) [![](https://docs.dojo.tech/images/dojo-icons/ClockCounterClockwise.svg) **Reversal** Learn how to reverse a payment with the Dojo API.](/payments/manage-payments/cancelling-payments/reversal) [![](https://docs.dojo.tech/images/dojo-icons/ArrowArcLeft.svg) **Refund** Find out how to refund a payment using the Dojo API.](cancelling-payments/refund) [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Need a hand?** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) --- ## Refund a payment >Find out how to refund a payment using the Dojo API. > **Tip:** This endpoint allows you to refund a Payment Intent without the user present. If you are looking for face-to-face refunds, please navigate to > [Terminal Sessions](https://docs.dojo.tech/payments/accept-payments/in-person-payments/pay-at-counter/terminals/create-session). Refunds return money to customers. A customer that returns a purchase needs a refund. You can refund the full amount, part of the amount, or make several partial refunds, as long as their total doesn't exceed the full original payment amount. You can only refund a payment after it has already been [captured](https://docs.dojo.tech/plugins/capture). If you want to use the Dojo for Business app for a refund, see [Refunding online checkout transactions](https://support.dojo.tech/hc/en-gb/articles/4408826217106-Refunding-and-reversing-online-checkout-transactions#h_01FK1SZJWY37BZKNMN0BQ3EYKF). ## Refund using the Dojo API To return a payment to your customer, use the endpoint below: > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api#tag/Refunds/operation/Refunds_Create In your request, include: * `paymentIntentId`: identifies the payment being refunded. * `amount`: the refund amount. * `idempotencyKey`: header parameter to recognize subsequent retries of the same request. Must be unique for each new refund for the payment intent. For the full API specification, see the [API reference](https://docs.dojo.tech/api#operation/Refunds_Create). ### Request example The next example below shows how you would refund 10.00 GBP. ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents//refunds \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic ' \ --header 'Version: 2024-02-05' \ --header 'IdempotencyKey: 656565gfyd65' \ --data '{ "amount": 1000, "refundReason": "Demo refund", "notes": "Duplicate transaction" }' ``` ### Response example If your request is successful, the response will return information about the refund. ```json { "message": "refund for the order 3443", "refundId": "rfnd_g8mCx87TykeQ6BOXqxZ9NQ" } ``` ## Cancel a refund Once created, the refund can't be canceled. As an option, you can create a new payment intent instead of the one that was refunded. --- ## Reverse a payment >Learn how to reverse a payment with the Dojo API. Use a reversal if you need to cancel a payment, for example if a customer has requested a payment to be canceled. You can reverse the full payment amount only. ## Reversal scenarios You can reverse a payment in the following scenarios: |State | `captureMode:Auto` | `captureMode:Manual` | |------|:------:|:-----:| |`Created`| ![no](https://docs.dojo.tech/images/dojo-icons-small/XCircle.svg) | ![no](https://docs.dojo.tech/images/dojo-icons-small/XCircle.svg) | |`Authorized`| N/A | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircleOneStar.svg#gh-light-mode-only)![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircleOneStarDarkMode.svg#gh-dark-mode-only) | |`Captured`| ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircleTwoStars.svg#gh-light-mode-only)![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircleTwoStarsDarkMode.svg#gh-dark-mode-only) | ![no](https://docs.dojo.tech/images/dojo-icons-small/XCircle.svg) | *   If reversed within 7 days of the original payment date. * * If reversed on the same calendar day as the original payment date. > **Info:** - Reversing a payment won't work in any other state. > - Once the reversal time limit expires, the payment can only be `refunded`. > - Payments that were `captured` in `captureMode:Manual` can only be [refunded](https://docs.dojo.tech/plugins/woocommerce/refund), and not `reversed`. If you want to reverse a payment using the Dojo for Merchants App, see [Reversing online checkout transactions](https://support.dojo.tech/hc/en-gb/articles/4408826217106-Refunding-and-reversing-online-checkout-transactions#h_01FK1T29A54JCYNZ9ZE4HK3G7T). ## Reverse using the Dojo API To reverse a payment, use the endpoint below: > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api#tag/Reversal/operation/Reversal_Create In your request, include: * `paymentIntentId`: This identifies the payment being reverse. For the full API specification, see the [reference](https://docs.dojo.tech/api#operation/Reversal_Create). ### Request example The next example below shows how you would reverse the payment intent `pi_pT08VyWG3EC_HQB4NBVliA`. ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents//reversal \ --header 'Authorization: Basic ' \ --header 'Version: 2024-02-05' ``` ### Response example If your request is successful, the response will return information about the reversal. ```json { "message": "reverse for the order 3443", "reversalId": "rvs_g8mCx87TykeQ6BOXqxZ9NQ" } ``` ## Cancel a reverse Once created, a reversal can't be canceled. You cannot reverse a reversal. You will have to create a new payment intent, instead. --- ## Capture a payment >Learn how to collect a pre-authorized payment with the Dojo Payments API. A created pre-authorized payment isn't complete until it has been **captured**. When completing a payment, you can capture the amount in full, or in partial increments. You can only capture a payment that hasn't yet been [refunded](https://docs.dojo.tech/plugins/woocommerce/cancelling-payments/refund) or [reversed](https://docs.dojo.tech/plugins/woocommerce/cancelling-payments/reversal). ## Capture using the Dojo API To capture a payment, use the endpoint: > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api#tag/Captures/operation/Captures_Create In your request, include: * `paymentIntentId`: This identifies the payment intent to be captured. * `amount`: This is the amount to capture. For the full API specification, see the [reference](https://docs.dojo.tech/api#operation/Captures_Create). ### Request example The next example shows the capture of 10.00 GBP. ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents/ \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic ' \ --header 'Version: 2024-02-05' \ --data '{ "amount": 1000 }' ``` ### Response example If your request is successful, the response will return information about the capture. ```json { "message": "collect payment for the order 3443", "captureId": "cp_itIiJMEAvES3ynYF_Yhs2g" } ``` --- ## Change amount >Learn how to use the Dojo Payments API to update payment. You can use the Payments API to alter configurable fields, including the payment and tip amount, after [creating the payment intent](https://docs.dojo.tech/plugins/woocommerce/payment-intent). Before you start, make sure that you have a payment intent that can be updated. By default, payment intents are unalterable and **can't** be updated. If you want to be able to update the payment, you must include `config` fields when creating the payment intent. These `config` fields should indicate which updates are allowed. In the following example, both the payment amount and the tip amount can be changed: ```json "config": { "payment": { "customAmountAllowed": true, "tipsAllowed": true } } ``` When the payment amount is changed, a new `clientSessionSecret` is generated. If previously generated, the old access token becomes invalid for payment processing. You must use the latest `clientSessionSecret` after any amount changes to complete the payment. You can only change an amount for payments before it has been [captured](https://docs.dojo.tech/plugins/woocommerce/capture). ## Change payment amount To change a payment amount, use the endpoint below: > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_SetCustomAmount In your request, include: * `paymentIntentId`: This identifies the specific payment intent. * `amount`: This is the new amount to be collected by this payment intent. For the full API specification, see the [reference](https://docs.dojo.tech/api#operation/PaymentIntents_SetCustomAmount). ### Request example The next example below shows how you would change the payment amount by 10.00 GBP. ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents/ \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic ' \ --header 'Version: 2024-02-05' \ --data '{ "amount": { "value": 1000, "currencyCode": "GBP" } }' ``` ### Response example If your request is successful, the response will return information about the changed payment intent. ```json { "id": "pi_pT08VyWG3EC_HQB4NBVliA", "captureMode": "Auto", "clientSessionSecret": "string", "clientSessionSecretExpirationDate": "2019-08-24T14:15:22Z", "status": "Created", "paymentMethods": [ "Card" ], "amount": { "value": 1000, "currencyCode": "GBP" }, "tipsAmount": { "value": 0, "currencyCode": "string" }, "requestedAmount": { "value": 0, "currencyCode": "string" }, "totalAmount": { "value": 1000, "currencyCode": "string" }, "reference": "string", "config": { "title": "string", "redirectUrl": "http://example.com", "cancelUrl": "http://example.com", "customerEmail": { "collectionRequired": false }, "details": { "showTotal": true, "showReference": true }, "billingAddress": { "collectionRequired": true }, "shippingDetails": { "collectionRequired": true }, "payment": { "customAmountAllowed": true, "tipsAllowed": true } } } ``` ## Change tip amount To change a tip amount, use the endpoint below: > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_SetTipsAmount In your request, include: * `paymentIntentId`: identifies the payment being changed. * `tipsAmount`: the tips amount. For the full specification, see the [API reference](https://docs.dojo.tech/api#operation/PaymentIntents_SetTipsAmount). ### Request example The next example below shows how you would change the tip's amount by 2.00 GBP. ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents/ \ --header 'Content-Type: application/json' \ --header 'IdempotencyKey: 656565gfyd65' \ --header 'Authorization: Basic ' \ --header 'Version: 2024-02-05' \ --data '{ "tipsAmount": { "value": 200, "currencyCode": "GBP" } }' ``` ### Response example If your request is successful, the response will return information about the changed payment intent. Here, you can see that the `tipsAmount` is now `200`, whereas in the original response body it was `0`. ```json { "id": "pi_pT08VyWG3EC_HQB4NBVliA", "captureMode": "Auto", "clientSessionSecret": "string", "clientSessionSecretExpirationDate": "2019-08-24T14:15:22Z", "status": "Created", "paymentMethods": [ "Card" ], "amount": { "value": 1000, "currencyCode": "GBP" }, "tipsAmount": { "value": 200, "currencyCode": "GBP" }, "requestedAmount": { "value": 0, "currencyCode": "string" }, "totalAmount": { "value": 1200, "currencyCode": "string" }, "reference": "string", "payment": { "customAmountAllowed": true, "tipsAllowed": true } } ``` ## Change request fails If a request fails, the unmodified payment intent can still be completed. If you want to increase the payment or tips amount, you might consider alternative options: * Capture the unmodified payment intent, then create a new payment intent to pay the additional amount. * Create a new payment intent with the same payments details, but with a new amount. After the payment intent is captured, cancel the original payment intent. --- ## Manage payments >Learn how to capture or reverse payments, retrieve payment details or change payments amount. [![](https://docs.dojo.tech/images/dojo-icons/Star.svg) **Payment intent** The first step in any integration.](/payments/manage-payments/payment-intent) [![](https://docs.dojo.tech/images/dojo-icons/Coins.svg) **Capture a payment** Manually collect an authorized payment.](/payments/manage-payments/capture) [![](https://docs.dojo.tech/images/dojo-icons/Calculator.svg) **Change amount** Manually change a payment amount.](/payments/manage-payments/change-amount) [![](https://docs.dojo.tech/images/dojo-icons/Email.svg) **Send a receipt** Send the receipt to your customer when the payment is made.](/payments/manage-payments/send-receipt) [![](https://docs.dojo.tech/images/dojo-icons/Close.svg) **Payment cancellation** Reverse, refund, or cancel payments.](/payments/manage-payments/cancelling-payments) [![](https://docs.dojo.tech/images/dojo-icons/PaymentCards.svg) **Setup intent** Save customer card details for future payments.](/payments/manage-payments/setup-intent) [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Need a hand?** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) --- ## Payment intent >Learn how to use payment intents and their lifecycle. We offer a full range of [online payment integrations](https://docs.dojo.tech/plugins/accept-payments), such as our prebuilt checkout page, payment links and components. Ultimately, these are all based on payment intents. ## How payment intents work The payment intent is the central entity of the [Dojo API](https://docs.dojo.tech/api), and the first thing any integration starts with. It contains payment details such as amount and currency, payment methods, and customer billing and shipping addresses. You can configure the payment intent object in various ways to suit your payment scenario. To create a payment when a customer purchases something from you, you [create a payment intent](https://docs.dojo.tech/plugins/woocommerce/introduction#create-a-payment-intent) using the POST [/payment-intents](https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_CreatePaymentIntent) endpoint and provide details of the purchase. We recommend using one payment intent per purchase. If the payment process was interrupted, you can resume it and reuse the same payment intent instead of creating a new one. Depending on how you want to capture payments, you need to choose one of the capture modes: * `Auto`: by default, payment intents are captured automatically without delay. Use this capture mode if you need to get paid immediately. This is ideal for accepting payments on your website or mobile app. * `Manual`: you need to explicitly request each payment intent is captured by making a request POST [/payment-intents/{paymentIntentId}/captures](https://docs.dojo.tech/api#tag/Captures/operation/Captures_Create). If the payment intent isn't captured within 7 days, it will be automatically reversed. Use this capture mode if you want to hold money on the customer’s card to collect them later or reverse it back to your customer. It's perfect if you’re a business that takes deposits or tabs, like a hotel or bar. Payment intents will progress through some combination of the statuses listed in the diagrams below. ![Payment Intent Flow](https://docs.dojo.tech/images/payment-intent-flow-auto.png) **Flow diagram: Payment Intent Flow Auto** ```mermaid stateDiagram-v2 state "Created" as created state "Captured" as captured state "Canceled" as canceled state "Reversed" as reversed state "Refunded" as refunded [*] --> created: POST /payment-intents created --> canceled: DELETE /payment-intents/{paymentIntentId} created --> captured: The customer fills the card details captured --> reversed: POST /payment-intents/{paymentIntentId}/reversal captured --> refunded: POST /payment-intents/{paymentIntentId}/refunds ``` ![Payment Intent Flow](https://docs.dojo.tech/images/payment-intent-flow-manual.png) **Flow diagram: Payment Intent Flow Manual** ```mermaid stateDiagram-v2 state "Created" as created state "Authorized" as authorized state "Captured" as captured state "Canceled" as canceled state "Reversed" as reversed state "Refunded" as refunded [*] --> created: POST /payment-intents created --> canceled: DELETE /payment-intents/{paymentIntentId} created --> authorized: The customer fills the card details authorized --> reversed: POST /payment-intents/{paymentIntentId}/reversal authorized --> captured: POST /payment-intents/{paymentIntentId}/captures captured --> refunded: POST /payment-intents/{paymentIntentId}/refunds ``` ## Create a payment intent To create a payment intent, use the endpoint below: > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_CreatePaymentIntent By default, it will be created with `captureMode: Auto`. To create a payment intent with `captureMode: Manual`, include this field in your request. For the full API specification, see the [API reference](https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_CreatePaymentIntent). ### Configurable fields You can include configurable fields when creating your payment intent. These fields can be changed later, while the payment intent is active, but before it is captured. In the next example, both the payment amount and the tip amount can be changed: ```json "config": { "payment": { "customAmountAllowed": true, "tipsAllowed": true } } ``` ### Request example The next example shows how to create a payment intent with `captureMode: Auto`. ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' \ --data '{ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order-0001", "paymentMethods": [ "Card", "Wallet" ] }' ``` The next example shows how to create a payment intent with `captureMode: Manual`. ```bash # The sandbox API key passed in 'authorization' is public. # Don’t submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2022-07-04' \ --data '{ "captureMode": "Manual", "autoExpireAt": "2023-12-01T00:00:00", "autoExpireAction": "Release", "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order-0001" }' ``` ## Check payment intent status Each payment intent transitions through several statuses throughout its lifetime. We recommend checking the status of your payment intent by subscribing to the [notifications](https://docs.dojo.tech/development-resources/webhooks). Also, you can check the status using the endpoint below: > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_Get In your request, include: * `paymentIntentId`: identifies the payment intent you want to check. For the full API specification, see the [API reference](https://docs.dojo.tech/api#operation/PaymentIntents_Get). ### Request example The next example shows how to check the status of the payment intent. ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request GET \ --url https://api.dojo.tech/payment-intents/\ --header 'Content-Type: application/json' \ --header 'Authorization: Basic ' \ --header 'Version: 2024-02-05' ``` The response will return information about the payment intent and its status. ---- ## More information [![](https://docs.dojo.tech/images/dojo-icons/TerminalWindow.svg) **API reference** Learn about the API and integrate with API endpoints.](/api) [![](https://docs.dojo.tech/images/dojo-icons/AnchorSimple.svg) **Webhooks** Subscribe to events to get notified of status changes in your payment intent.](../../../../development-resources/webhooks) --- ## Save card vs Setup intent > Learn how Save card functionality is different from Setup intent. While save card and setup intent are both used to save a card, they are used in different scenarios. The following table explains the differences between the two: | Use case | Save card | Setup intent | |-------------------| --- | --- | |Basic | Save card is used to save a card for future use by a customer. | Setup intent is used to save a card for a future charge used by a merchant and to verify the card. The merchant saves the payment method. | |Impact on customers| When a customer makes a payment, they often have the option to save their payment information for future transactions. This is particularly convenient for customers who frequently make online purchases. When a customer opts to save their card, the payment gateway securely stores the card details and associates them with the customer's account. Subsequent transactions can then be made without the need for the customer to re-enter their card details. | A setup intent is a concept used in Payment Intents API to add a payment method, typically for a future charge. It's commonly used in scenarios where a merchant collects customer's payment details and charges their card later. | |Scenario | Save card is used when a customer wants to save their card details for future use. | Setup intent is used when a merchant wants to save a card for a future charge. | |Security | The customer needs to enter card details and go through 3DS checks when making a payment.| The customer does not go through 3DS checks when a card is charged.| |Payment flow | The customer initiates the payment flow and saves the card details.| The merchant initiates the payment flow and saves the card details.| |Card access | The customer can access all saved cards.| The merchant cannot access the previously saved cards.| |API method | Save card is part of Payment intents API.| Setup intent is done using Setup intents API.| --- ## Save card for future use > Learn more about **Save Card** functionality for later use. You can provide your customers with the ability to save their card information securely for any payments they make in the future. This allows them to set their preferred payment card, reducing the need to enter card information repeatedly. This is a nice-to-have feature, however, this is optional. The save card functionality enables you to complete a transaction without storing your customer's payment card details on your server. The following images are a demonstration of this feature within a checkout page. ## Scenarios - **Repeat Purchases** Gabriel frequently orders groceries online from his favorite supermarket. He opts to save his card details during checkout to expedite future purchases. With this, Gabriel can quickly reorder groceries without having to manually enter his payment information each time, saving him time and effort. He only has to add his CVV code to make a payment. --- ## Step-by-step guide(Save-card) > Learn how to integrate **Save Card** functionality using Dojo's hosted checkout page for later use. Follow the step-by-step guide to integrate save card functionality to your checkout page. > **Info:** - Dojo understands that each checkout page is built differently. The steps listed serve as a good reference to build this feature into your checkout page. ![Save card web flow](https://docs.dojo.tech/images/save-card-web-flow.png) **Flow diagram: Save Card Web Flow** ```mermaid sequenceDiagram actor U as User participant CP as dojo checkout page participant MF as Merchant Frontend participant MB as Merchant backend participant DB as dojo backend U->>MF: Clicks Checkout MF->>MB: Sends information about customer's purchase MB->>DB: POST /customers/{customerId}/create-secret DB-->>MB: Return a customer-secret Note right of MB: Create a payment intent and add customer IDand secret to `customer`, and SavedCardto `paymentMethods`. MB->>DB: POST /payment-intents DB-->>MB: Returns a payment intent object with payment link MB-->>MF: Returns a payment intent object with payment link MF->>CP: Redirect to Checkout Page from the payment link U->>CP: Selects Save card for future use and clicks Pay CP->>DB: Sends payment details for processing DB->>MB: Sends webhook with the payment result DB-->>CP: Notifies about the payment result CP-->>U: Presents the payment result CP-->>MF: Notifies about the payment result Note over MF,DB: When checking out next time, if Save card for future use was selected at the time of payment, the card will be saved for that customer. ``` ### Step 1: Create a new customer or retrieve an existing customer - If you don't have a Dojo user linked to your backend user, [create a new one](https://docs.dojo.tech/api#tag/Customers/operation/Customers_Create) using POST[/customers](https://docs.dojo.tech/payments/api#tag/Customers/operation/Customers_Create). - If you already have a `customerId`, retrieve it. > **Info:** - Don't create a new customer for each transaction. This prevents customers from accessing their saved cards. > > > ### Step 2: Create a customer secret key > > To set up saved cards or retrieve information about saved cards for a specific customer, you must create and pass a [customer secret](https://docs.dojo.tech/api#tag/Customers/operation/Customers_CreateCustomerSecret) using POST [/customers/{customerId}/create-secret](https://docs.dojo.tech/payments/api#tag/Customers/operation/Customers_CreateCustomerSecret). > > **Info:** > - You must always create a customer `secret` at your backend and then pass it to your checkout page. > - Never store sensitive data such as API Keys inside your checkout page. > - Customer `secret` is short-lived, hence Dojo recommends creating a new one each time your app might need to access stored payment methods. The following code samples demonstrate how to create a customer `secret`. ```bash title="create-customer-secret.sh" # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/customers/cust_sandbox_6g-HvPv6VkG_Q_PXCpJqmw/create-secret \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' ``` ### Step 3: Create a payment intent linked to the customerId For every payment intent you create, you must pass the customer's `id`, `secret` to the payment intent request body and enable `SavedCard` parameter inside `paymentMethods`. The customer secret key is a confidential identifier linked to individual customers. ```javascript "paymentMethods": ["SavedCard", "Card"], "customer": { "id": "cust_sandbox_vjUhNwRjBE2xSeLVS_DFyQ", "secret": "cs_sandbox_" } ``` ### Step 4: Initiate payment flow in the checkout page Display the payment link to the customer to start the checkout process. The payment link can be obtained from the response body. An example of the reponse body with payment link displayed and `savedCard` enabled would look like: ```javascript { "id": "pi_sandbox_gii78EXbJEyeVnuBglFgQA", "captureMode": "Auto", "cardHolderNotPresent": false, "clientSessionSecretExpirationDate": "0001-01-01T00:00:00Z", "status": "Created", "paymentMethods": [ "SavedCard", "Card" ], "amount": { "value": 1000, "currencyCode": "GBP" }, "totalAmount": { "value": 1000, "currencyCode": "GBP" }, "refundedAmount": 0, "customer": { "id": "cust_sandbox_vjUhNwRjBE2xSeLVS_DFyQ" }, "createdAt": "2024-04-02T14:21:35.402137Z", "updatedAt": "2024-04-02T14:21:35.402137Z", "reference": "Order 234", "description": "Demo payment intent", "itemLines": [], "taxLines": [], "merchantConfig": { "supportedPaymentMethods": { "cardSchemes": [ "VISA", "MASTERCARD", "MAESTRO", "DISCOVER", "DCI" ], "wallets": [ "APPLE_PAY", "GOOGLE_PAY" ] } }, "config": { "branding": {}, "tradingName": "Cam Test Ltd" }, "paymentSource": "api", "expireAt": "2024-05-02T14:21:35.402204Z", "metadata": { "location-id": "rpl_bOppxLvOEsS" }, "paymentEvents": [], "paymentLink": "https://pay.dojo.tech:443/checkout/pi_sandbox_gii78EXbJEyeVnuBglFgQA?cid=cust_sandbox_vjUhNwRjBE2xSeLVS_DFyQ&csc=cs_sandbox_xrLk_6EwFBiRXRDkDYu6-bxy1XwXxoF1YiNvyCY4er5DfxE_SsF8SlPqY6FNnPcxd91Y9d19U4-Brye4XGoXJZBTOijo6BUo-DS2qL6KjTHmZlJC--jkiaUlu3v6XA7tPrJnfSz6ary2xjculxEia5bdIBkfh-Bo8sj2GoKF0v8&cpm=pm_RDg255vaRu6RRHluXQLG1A", "terminalSessionHistory": [] } ``` {/* Code samples pending Code samples pending */} ### Step 5: Receive payment status Once payment is completed, you get a notification with a numerical code representing the result. Check out the [status codes](https://docs.dojo.tech/payments/accept-payments/online-payments/components/configuration#status-code) reference for more information about what each code means. Additionally, your backend will receive a notification via [Webhook](https://docs.dojo.tech/development-resources/webhooks). ## Setting a preferred payment card You can enable customers having multiple saved cards to set a preferred payment card. This allows for seamless checkout experiences, as their preferred card will be automatically selected for future transactions. To set a preferred card, do the following: > **Info:** Dojo assumes you have already set up your client side to allow customers to select their preferred card. The API allows you to specify a preferred method ID, which preselects the card during checkout. ![Save card preferred payment](https://docs.dojo.tech/images/save-card-web-preferred-payment.png) 1. Before creating a payment intent, retrieve the payment method for an existing customer using the GET[/customers/public/{customerId}/payment-methods](https://docs.dojo.tech/api#tag/Customers/operation/Customers_GetPaymentMethods) endpoint. Set the following parameters to get started: - **API key**: To authenticate the payment, add your customer `secret` as the API key. For example: `cs_sandbox_`. - **`customerId`**: To authenticate a payment against a particular customer, add the customer ID you created in [step 1](https://docs.dojo.tech/plugins/woocommerce/introduction#step-1-create-a-new-customer-or-retrieve-an-existing-customer). This returns an `id` for the saved method. A sample response looks like the following: ```json { "customerId": "cust_sandbox_vjUhNwRjBE2xSeLVS_DFyQ", "merchantId": "771402011592305", "savedPaymentMethods": [ { "id": "pm_RDg255vaRu6RRHluXQLG1A", "cardDetails": { "pan": "44565300****1096", "expiryDate": "2024-12-31", "scheme": "VISA" } }, { "id": "pm_Lpgcm_7XSb2ydNFkgZ9Czg", "cardDetails": { "pan": "52000000****1005", "expiryDate": "2024-12-31", "scheme": "MASTERCARD" } } ], "supportedPaymentMethods": { "cardSchemes": [ "VISA", "MASTERCARD", "MAESTRO", "AMEX" ] } } ``` 2. Pass this ID as `SavedCardId` to your client side when creating a payment intent under `customer` using POST[/payment-intents](https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_CreatePaymentIntent). ```json { "paymentMethods": ["SavedCard", "Card"], "customer": { "id": "cust_sandbox_vjUhNwRjBE2xSeLVS_DFyQ", "secret": "cs_sandbox_xrLk_6EwFBiRXRDkDYu6-bxy1XwXxoF1YiNvyCY4er5DfxE_SsF8SlPqY6FNnPcxd91Y9d19U4-Brye4XGoXJZBTOijo6BUo-DS2qL6KjTHmZlJC--jkiaUlu3v6XA7tPrJnfSz6ary2xjculxEia5bdIBkfh-Bo8sj2GoKF0v8", "SavedCardId": "pm_RDg255vaRu6RRHluXQLG1A" } } ``` The `SavedCardId: pm_RDg255vaRu6RRHluXQLG1A` is the payment card that was set by your customer as the preferred card for future transactions. It will be automatically pre-selected for all future payments unless you add another saved card ID from the list of GET [/customers/public/{customerId}/payment-methods](https://docs.dojo.tech/api#tag/Customers/operation/Customers_GetPaymentMethods). At your client side, this ID should be valid until the customer decides to remove it or chooses another card as their preferred option. --- ## Send a receipt >Learn how to email receipts with the Dojo Payments API. Dojo will automatically send an email receipt to a customer once they have successfully paid. The customer email is provided earlier, when creating the [payment intent](https://docs.dojo.tech/plugins/woocommerce/payment-intent), inside the `Customer` schema object: ```json "customer": { "emailAddress": "client@gmail.com", "phoneNumber": "078654321" } ``` Each payment has a receipt history which you can view in the Dojo for Business App. ## Send additional emails You can manually send additional receipts to customers. To do this use the endpoint below: > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api#tag/Payment-intents/operation/Receipt_Create In your request, include: * `emails`: the list of email addresses to which the receipt should be sent. For the full specification, see the [API reference](https://docs.dojo.tech/api#operation/Receipt_Create). ### Request example The next example below shows how you would capture 10.00 GBP. ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents//receipt \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic ' \ --header 'Version: 2024-02-05' \ --data '{ "emails": [ "gabriel@dojo.com", "mari@dojo.com" ] }' ``` ### Response example If your request is successful, the response will return an empty object. --- ## Setup intent > Learn more about [Setup Intent](https://docs.dojo.tech/api#tag/Setup-intents)API. You can use the [Setup Intent](https://docs.dojo.tech/api#tag/Setup-intents)API for a future payment or an advanced booking, or in any other scenario where you need to save a customer's payment information for future use. Please note that this setup intent can only be used once, and subsequent charges will need to be re-authorized by creating a new setup intent ID. ## How do setup intents work? Using a Setup Intent is an easy way to collect card details for future payments. You can configure the object with or without an intended amount based on your business’ terms and conditions. The setup intent is available in `captureMode: Auto` only. For the full API specification, see the [Setup Intent API guide](https://docs.dojo.tech/api#tag/Setup-intents). ## Merchant-Initiated Transactions A merchant-initiated transaction is a payment that is initiated by the merchant, rather than the customer. Merchants can set up certain terms for a one-time payment or several other payments that will be captured in the future. The customer agrees to the merchant’s terms before sharing card details and authorizing the payment. ### Types #### **NoShow** A `NoShow` transaction occurs when a customer is unable to fulfill the merchant-initiated terms. For example, when a customer makes a reservation at a restaurant but does not show up without canceling the reservation in advance. This can be a major problem for restaurants, as they lose out on potential revenue. #### **Unscheduled** An `Unscheduled` transaction occurs when a merchant saves the payment information of a customer and subsequently initiates a transaction without a predetermined schedule or regular frequency. This type of transaction can involve either a fixed or variable amount, depending on the merchant's terms and conditions. An `Unscheduled` transaction is typically not part of a recurring billing or subscription arrangement. Instead, a card is charged only after the customer's prior authorization or request. You can initiate a setup intent with a `NoShow` or `Unscheduled` condition. Add the following to the Setup Intent request body: ```json { ... "MerchantInitiatedTransactionType": "NoShow", } ``` > **Note:** In case of a `NoShow`, the card can be charged only once. > > ## Setup intent API vs Payment intent API > > Setup Intent and Payment Intent serve different purposes in the world of payments. > > - The [Setup Intent](https://docs.dojo.tech/api#tag/Setup-intents)API is ideal for scheduling a payment for the future and does not charge the customer's card right away. This API allows merchants to save a card to charge later. The Setup Intent API works with `captureMode: Auto` only. To charge a card, you need to create a payment intent. > > - The [Payment Intent](https://docs.dojo.tech/api#tag/Payment-intents)API is ideal for creating a payment that processes immediately, or within a defined timeframe. No card details are saved in a payment intent API object when created. The payment intent API works with both `captureMode: Auto` and `captureMode: Manual`. You can collect card details and capture a payment with the same payment intent. > > ## Business use cases > > The following are some common business use cases for setup intents. > > - Online Hotel Reservation systems in which customer card details are required to be collected in advance when making a booking. The hotel is then able to charge the customer during check-out without re-presenting of the card. > - Online table booking in a restaurant that collects customer card details in advance when booking a table for a party of 10 or more. The restaurant is then able to charge the card once the booking is completed. > > --- > > ## Step-by-step guide(Setup-intent) > > Learn how to create a setup intent and charge the card using the API. > > During its lifecycle, the [Setup Intent](https://docs.dojo.tech/api#tag/Setup-intents) goes through a combination of the following statuses, depending upon your requirements. > > |Status|Description| > |:----|:----| > |`Created`| The setup intent is created.| > |`Authorized`| The customer adds their card details and authorizes the setup intent.| > |`Expired`| The setup intent expired after creation.| > |`CardExpired`| The card entered has passed the expiry date and is no longer usable.| > |`Canceled`| The setup intent in `created` state is deleted.| > |`Completed`| The setup intent cycle is complete and the merchant has charged the customer's card.| > |`Closed`| The authorized setup intent is also deleted. This is applicable when you set `includeAuthorized` to `true` using the [`DELETE /setup-intents`](https://docs.dojo.tech/api#tag/Setup-intents/operation/SetupIntents_Delete) endpoint.| > > ## Flow diagram > > ![Setup Intent Flow](https://docs.dojo.tech/images/setup-intent.png) > > Follow the steps below for a complete setup intent flow: > ## Step 1: Create a setup intent > To create a setup intent, use the following endpoint: > > POST [/setup-intents](https://docs.dojo.tech/api#tag/Setup-intents/operation/SetupIntents_Create) > > In your request body, include the following: > > - `reference`: A reference number to track. > - `intendedAmount`: The amount you intend to collect from a customer in the future after a payment method is attached. > - `merchantInitiatedTransactionType`: The transaction type you intend to set up. > - `terms`: The agreed terms between you and your customer. > > **Info:** - When configuring the `intendedAmount`, a customer will not be charged right away. The charge **may** vary depending upon the terms agreed between a customer and a merchant. > - By default, you can create a setup intent with `captureMode: Auto` only. #### Request example The following code sample demonstrates creating a setup intent of 10.00 GBP. ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url 'https://api.dojo.tech/setup-intents' \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' \ --data '{ "reference": "Dojo Cafe | Booking request for Table 4", "merchantInitiatedTransactionType": "NoShow", "terms": "In case of no-show, the customer authorizes us to charge their card with table booking fee.", "intendedAmount": { "value": "1000", "currencyCode": "GBP" } }' ``` Once you've created a setup intent, the status is updated to . ## Step 2. Redirect your customer to Dojo's Checkout page After receiving the request, Dojo creates a setup intent and returns its unique ID in the following format: ```json { "id": "si_sandbox_Oh69aQaQMUuNIPJcPrcRwQ", ... } ``` 1. Return this ID to the client-side and use it to create a link in the following format: `https://pay.dojo.tech/checkout/{{id}}` 2. Redirect your customer to the link on your client-side: ```js title="online-checkout-client.html" .then(response => response.json()) .then(function (data) { var redirectLink = "https://pay.dojo.tech/checkout/" + data.id window.location.replace(redirectLink) }); ``` After your customer fills in their payment information on the **Checkout** page, Dojo server-side saves the card details and redirects the customer to the success page. Once your customer authorizes their card in the setup intent, the status is updated to . ## Step 3: Create a payment intent and charge the card After a setup intent has been created and authorized, you can use the `setupIntentId` to create a payment intent and charge the card. When you are ready to charge the card, create a payment intent and then use the payment intent charge endpoint. > **Info:** - You can charge the full amount only. > - For the payment intent you create, you can charge a card only once. ### Charge a card using the Dojo API To complete the process of charging a card, ensure you do the following: 1. Create a payment intent and pass the `setupIntentId` to the request. > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_CreatePaymentIntent ```json { ... "setupIntentId": "si_sandbox_", } ``` **Request example** The following code sample demonstrates creating a payment intent of 10.00 GBP using the setup intent ID created in [step 1](https://docs.dojo.tech/plugins/woocommerce/introduction#step-1-create-a-setup-intent): ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url 'https://api.dojo.tech/payment-intents' \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' \ --data '{ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Dojo Cafe | Table no. 4.", "setupIntentId": "" }' ``` Once you create a payment intent to charge the card, the setup intent status is still . 2. Then initiate a charge to complete the process: > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_ChargePaymentIntent In your request, include: `paymentIntentId`: This identifies the payment intent to be charged. **Request example** The following code sample demonstrates initiating a charge of 10.00 GBP against the payment intent ID created in the above step: ```bash # The sandbox API key passed in 'authorization' is public. # Don’t submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents/pi_sandbox_Dcqx7k8pUUKedgB6wD1J1A/charge \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' ``` Once you charge the card successfully, the setup intent status is updated to . ## Check setup intent status > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/api#tag/Setup-intents/operation/SetupIntents_GetById Every time you perform an action with the [Setup Intent](https://docs.dojo.tech/api#tag/Setup-intents/operation/SetupIntents_Create)API, it transitions through a state. We recommend that you subscribe to [notifications](https://docs.dojo.tech/development-resources/webhooks) to check the current status of your setup intent. In your request, include: `setupIntentId`: identifies the setup intent you want to track. For the full API specification, see the [API reference](https://docs.dojo.tech/api). #### Request example The following example shows how to check the status of the setup intent: ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url 'https://api.dojo.tech/setup-intents/si_sandbox_Oh69aQaQMUuNIPJcPrcRwQ' \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' ``` The response will return information about the setup intent and its status. --- ## Tokenization > **Info:** Before proceeding with development against this API specification, please note that you will need to be able to provide evidence of attestation of [PCI DSS SAQ-D](https://www.pcisecuritystandards.org/), indicating that you are compliant with industry requirements with regard to safely handling cardholder data. > A certificate of compliance must be provided to Dojo annually for continued usage of our tokenization services. The **Tokenization API** allows for customer card details captured by your server (such as through an i-frame) to be passed to Dojo for authorization. These card details can then be charged immediately or stored against a token for a later time. ## Setup Intents Using a Setup Intent is an easy way to collect card details for a future payment. You can configure the object with or without an intended amount based on the business’ terms and conditions. The [Setup Intent](https://docs.dojo.tech/api#tag/Setup-intents)API, within the context of Tokenization is ideal for scheduling a payment for the future using card details entered client-side and captured by your server. These details are tokenized during the authorization process and a token ID will be returned (subsequently referred to as `setupIntentId`). A setup intent does not charge the customer's card right away: to then charge the card, you need to create a payment intent referencing the aforementioned token ID. For the full API specification, see the [Setup Intent API guide](https://docs.dojo.tech/api#tag/Setup-intents). ## Business use cases The following are some common business use cases for the Tokenization API. - Online Hotel Reservation systems in which customer card details are required to be collected in advance when making a booking. The hotel is then able to charge the customer during check-out without re-presenting of the card. - Online table booking in a restaurant that collects customer card details in advance when booking a table for a party of 10 or more. The restaurant is then able to charge the card once the booking is completed. --- ## Step-by-step guide(Tokenization) >Learn how to create a setup intent and charge the card using the API. During its lifecycle, the [Setup Intent](https://docs.dojo.tech/api#tag/Setup-intents) goes through a combination of the following statuses, depending upon your requirements. |Status|Description| |:----|:----| |`Created`| The setup intent is created.| |`Authorized`| The customer adds their card details and authorizes the setup intent.| |`Expired`| The setup intent expired after creation.| |`CardExpired`| The card entered has passed the expiry date and is no longer usable.| |`Canceled`| The setup intent in `created` state is deleted.| |`Completed`| The setup intent cycle is complete and the merchant has charged the customer's card.| |`Closed`| The authorized setup intent is also deleted. This is applicable when you set `includeAuthorized` to `true` using the [`DELETE /setup-intents`](https://docs.dojo.tech/api#tag/Setup-intents/operation/SetupIntents_Delete) endpoint.| ## Flow diagram ![Setup Intent Flow](https://docs.dojo.tech/images/tokenization/tokenization-flow.jpg) **Flow diagram: Tokenization Flow** ```mermaid stateDiagram-v2 direction TB state "Created" as SetupCreated state "Authorized" as Authorized state "Completed" as Completed [*] --> SetupCreated: Create a setup intentPOST pci-api.dojo.tech/setup-intents SetupCreated --> Expired SetupCreated --> CardExpired SetupCreated --> Canceled: DELETE /setup-intents/{setupIntentId} SetupCreated --> Authorized state "Create a Payment Intent" as PI_Box { state "Created" as PICreated state "Captured" as PICaptured PICreated --> PICaptured: POST /payment-intents/{paymentIntentId}/charge } Authorized --> PICreated: POST api.dojo.tech/payment-intents PICaptured --> Completed: GET api.dojo.tech/setup-intents/{setupIntentId} %% Styling style SetupCreated fill:#40E0D0,stroke:#333 style Authorized fill:#40E0D0,stroke:#333 style Completed fill:#40E0D0,stroke:#333 style PICreated fill:#A4B0F5,stroke:#333 style PICaptured fill:#A4B0F5,stroke:#333 ``` ## Step 1: Capture customer card details Firstly, the customer's card details must be entered, such as into an i-frame, and securely captured by the client server. > **Note:** In order to handle and store cardholder data, you will need to be able to provide evidence of attestation for [PCI DSS SAQ-D](https://www.pcisecuritystandards.org/), indicating that you are compliant with industry requirements with regard to the safe handling of this data. > A certificate of compliance must be provided to Dojo annually for continued useage of our tokenization services. ## Step 2: Create a setup intent and authorize the card To authorize and tokenize the captured cardholder data for a future payment, you must create a setup intent via a POST to the unique URL and endpoint below: > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/pci-api/api#tag/SetupIntents/operation/SetupIntents_Create > **Info:** The creation of the initial setup intent for tokenization is the only instance in which the [pci-api.dojo.tech](https://docs.dojo.tech/plugins/woocommerce/pci-api.dojo.tech) URL is invoked. Follow-up setup intent calls referencing the created intent must be made to [api.dojo.tech](https://docs.dojo.tech/plugins/woocommerce/api.dojo.tech). > > > Dojo will attempt to authorize against the card details provided and then respond by confirming in the response body the details of the setup intent and attempted authorization, such as the `status`, time of creation and an `id` to be referenced in future calls. If the returned `status` is "Authorized", the card can then be charged by creating a payment intent. > > Once you've created a setup intent, the status is updated to . > > ## Step 3: Create a payment intent and charge the card > > After a setup intent has been created and authorized, you can use the `setupIntentId` (created in [step 2](https://docs.dojo.tech/plugins/woocommerce/introduction#step-2-create-a-setup-intent-and-authorize-the-card)) to create a payment intent and charge the card. When you are ready to charge the card, create a payment intent and then use the payment intent charge endpoint. > > **Info:** - You can charge the full amount only. > - You can only charge a card once. ### Charge a card using the Dojo API To complete the process of charging a card, ensure you do the following: 1. Create a payment intent and pass the `setupIntentId` to the request. > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_CreatePaymentIntent ```json { ... "setupIntentId": "si_sandbox_", } ``` **Request example** The following code sample demonstrates creating a payment intent of 10.00 GBP using the setup intent ID: ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url 'https://api.dojo.tech/payment-intents' \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' \ --data '{ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Dojo Cafe | Table no. 4.", "setupIntentId": "" }' ``` Once you create a payment intent to charge the card, the setup intent status is still . 2. Initiate a charge to complete the process: > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_ChargePaymentIntent In your request, include: `paymentIntentId`: This identifies the payment intent to be charged. **Request example** The following code sample demonstrates initiating a charge of 10.00 GBP against the payment intent ID created in the above step: ```bash # The sandbox API key passed in 'authorization' is public. # Don’t submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents/pi_sandbox_Dcqx7k8pUUKedgB6wD1J1A/charge \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' ``` Once you charge the card successfully, the setup intent status is updated to . ## Step 4: Check setup intent status > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/api#tag/Setup-intents/operation/SetupIntents_GetById Every time you perform an action with the [Setup Intent](https://docs.dojo.tech/api#tag/Setup-intents/operation/SetupIntents_Create)API, it transitions through a state. We recommend that you subscribe to [notifications](https://docs.dojo.tech/development-resources/webhooks) to check the current status of your setup intent. In your request, include: `setupIntentId`: identifies the setup intent you want to track. For the full API specification, see the [API reference](https://docs.dojo.tech/api). #### Request example The following example shows how to check the status of the setup intent: ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url 'https://api.dojo.tech/setup-intents/si_sandbox_Oh69aQaQMUuNIPJcPrcRwQ' \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' ``` The response will return information about the setup intent and its status. --- ## Order and Pay > This section covers integrating with Dojo Order and Pay. Order and Pay is an integrated, self-service solution that enables the creation and management of [orders](https://docs.dojo.tech/core-concepts/orders) on the POS without the need for physical hardware, as well as the paying of those orders from a customer device or other Dojo product, empowering customers with a seamless, integrated experience. Customers can interact with a visual menu on their device to place orders and complete payment, or pay later from the same interface. These updates are shared with the POS in real-time, allowing busy venues to serve customers faster. ## Order Entity The [Order](https://docs.dojo.tech/core-concepts/orders) entity represents the core component of the Ordering API, containing all relevant information about an order placed by customers at a given location. An order can consist of multiple items, each with details such as status, quantity, price, and applied modifiers. ## Order Status The Order Status represents the various stages in an order’s lifecycle. As an order progresses from creation to fulfilment, its status will update to reflect its current state. | **Status** | **Description** | | --- | --- | | `New` | The order has been created but has not yet been processed. | | `Submitted` | The order has been submitted to the POS and is awaiting confirmation. | | `Confirmed` | The order has been confirmed by the POS and is awaiting preparation. | | `Accepted` | The order has been accepted by the kitchen or staff for preparation. | | `Preparing` | The items in the order are currently being prepared. | | `Prepared` | The items have been fully prepared and are ready for service or collection. | | `Ready` | The order is ready for delivery or collection by the customer. | | `Finalized` | The order has been completed and paid for, and no further changes can be made. | | `Canceled` | The order has been canceled and is no longer active. | | `Failed` | The order has encountered an error and failed to process. This may require further investigation. | These statuses help track the state of each order and ensure that any integrated systems can react to updates in a consistent manner. ## Capabilities In the Dojo EPOS Data API, **capabilities** represent specific actions that the POS system can perform. These capabilities are linked to corresponding API endpoints in the POS system. By defining these capabilities, the POS system communicates to Dojo which features are supported and accessible. See [Registering capabilities](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities) for how each capability is registered with Dojo. **Registering a capability:** the heading for each capability below (for example `SearchOrders`, `GetOrderById`, `CreateOrderLock`, `RecordOrderPaymentById`) is the exact `name` value to send in the body of `PUT /epos/integrations/rest` or `PUT /epos/integrations/ws`. The version is sent alongside as a separate field (`"version": "v1"`); appending `V1` to the heading gives you the wire-level method Dojo invokes after registration (for example `RecordOrderPaymentByIdV1`). See [Registering capabilities](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities) for the full body schema. For backwards compatibility, registration also accepts the four legacy names `GetOrderBill`, `RecordOrderPayment`, `UpdatePartyById`, and `UpdateReservationById` — they are equivalent to `GetOrderBillById`, `RecordOrderPaymentById`, `UpdateParty`, and `UpdateReservation` respectively. New integrations should prefer the wire-aligned form shown in the headings below. ### CreateOrder > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-post-orders > See OpenAPI spec for CreateOrderV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-CreateOrderV1_Request This capability allows the creation of new orders within the POS system. It is essential for handling customer orders and storing relevant order details. ### GetOrderById > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-get-orders-orderId > See OpenAPI spec for GetOrderByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-GetOrderByIdV1_Request This capability enables Dojo to retrieve detailed information about a specific order using its unique order ID. This is crucial for order tracking and status updates. ### CancelOrderById > See OpenAPI spec for DELETE endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-delete-orders-orderId > See OpenAPI spec for CancelOrderByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-CancelOrderByIdV1_Request This capability provides the ability to cancel an order within the POS system, preventing further modifications or processing. Cancellations are performed using the order’s unique ID. The POS system can reject a `CancelOrder` reqeuest if the order is not in a state where it can be cancelled. ### SearchOrders > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/paths/~1v1~1orders~1search/post > See OpenAPI spec for SearchOrdersV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-SearchOrdersV1_Request This capability enables searching for orders based on various criteria. It supports filtering and pagination to help Dojo products efficiently find orders within the POS system. Each Dojo product has different requirements on what filters must be implemented which can be found on the product documentation page(s). ### RecordOrderPaymentById > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-post-record-order-payment > See OpenAPI spec for RecordOrderPaymentByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-RecordOrderPaymentByIdV1_Request This capability allows Dojo to record a payment against an order. All payments recorded this way will be sent with their `paymentIntentId` which is unique and can be used for both deduplication and to control the lifecycle of the payment with operations like Get and Reversal. --- ## Flows > **Info:** The capabilities mentioned on this page must be registered with the **EPOS Capabilities API** prior to initiating an Order and Pay flow, > learn more [here](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities). The following diagram demonstrates how the **Order and Pay** product will interact with Dojo and the POS system for creating orders and completing payments: ![](https://docs.dojo.tech/images/order-and-pay/order-and-pay-flow.jpg) **Flow diagram: Order And Pay Flow** ```mermaid sequenceDiagram actor C as Customer participant B as DOJO Backend participant P as POS C->>B: Create order B->>B: Create payment intent B-->>C: Redirect to checkout C->>B: Completes checkout flow B->>B: Dojo captures payment B->>P: CreateOrder P->>P: Record payment, update order status P-->>B: 200 OK B-->>C: Order confirmation ``` # Step-by-step: Order and Pay ## Step 1: Customer creates order to Dojo The first stage of the Order and Pay flow is triggered when a customer, having accessed a list of venue products using the Dojo Order and Pay interface, creates an order by adding one or more items to the basket and advancing to the payment screen. ## Step 2: Dojo creates a Payment Intent and captures the payment **Main Page**: [Payment Intents](https://docs.dojo.tech/payments/manage-payments/payment-intent) Once the order has been initiated via the Order and Pay interface, Dojo will pre-authorise the payment by creating a Payment Intent and initiating a checkout flow for the customer. This payment is to be captured once the POS has confirmed the order. This also generates a Payment Intent which can be used to recall payment details such as the authorization code, card type and receipt data upon payment completion. ## Step 3: Dojo creates an order on the POS > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-post-orders > See OpenAPI spec for CreateOrderV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-CreateOrderV1_Request **Main page**: [Orders](https://docs.dojo.tech/core-concepts/orders) The next step in is for Dojo to create the customer order within the POS, using the `CreateOrder` capability. The request will contain fields such as item data, type of order and payment details, including the `paymentIntentId`. It may also contain any additional modifiers or discounts, for example, if specified. The POS should respond to Dojo with a 200 response to confirm that this has been received and that the payment has been acknowledged and recorded, and the response should inlcude additional data such as the relevant status. > **Info:** In any calls made from the POS to Dojo through the [Dojo API](https://docs.dojo.tech/api), such as to [retrieve the Payment Intent status](https://docs.dojo.tech/payments/manage-payments/payment-intent#check-payment-intent-status), Dojo will refer to the POS "order ID" by `externalId`, this can be useful when retrieving payment details such as receipt data upon payment completion, for example. ## Step 4: Dojo displays order status to customer After receiving a successful response from the POS to the RecordOrderPaymentById request, Dojo will inform the customer of the outcome and given order status through the **Order and Pay** customer interface. The following diagram demonstrates how the **Order and Pay** product will interact with Dojo and the POS system to exclusively complete payments: ![](https://docs.dojo.tech/images/order-and-pay/pay-only-flow.jpg) **Flow diagram: Pay Only Flow** ```mermaid sequenceDiagram actor C as Customer participant B as DOJO Backend participant P as POS C->>B: Request open orders B->>P: SearchOrders P-->>B: List of open orders B-->>C: Show open orders C->>B: Choose order to pay B->>P: GetOrderById P-->>B: GetOrderById response B->>B: Create payment intent B-->>C: Redirect to checkout C->>B: Completes checkout flow B->>B: Dojo captures payment B->>P: Record Payment request P->>P: Record payment, update order status P-->>B: Record Payment response B-->>C: Show updated order ``` # Step-by-step: Pay-only ## Step 1: Customer retrieves orders > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/paths/~1v1~1orders~1search/post > See OpenAPI spec for SearchOrdersV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-SearchOrdersV1_Request **Main page**: [Orders](https://docs.dojo.tech/core-concepts/orders#search-orders) The first stage of the pay-only flow is triggered when a customer attempts to retrieve open orders using the Order and Pay interface. Dojo will request these from the POS using the [SearchOrders](https://docs.dojo.tech/capabilities/orders) capability, refining the request by certain filters such as table ID. Once Dojo has received the orders requested, these will be displayed to the customer for selection. ## Step 2: User selects order, Dojo requests order details > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-get-orders-orderId > See OpenAPI spec for GetOrderByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-GetOrderByIdV1_Request **Main page**: [Orders](https://docs.dojo.tech/core-concepts/orders#get-order-by-id) The user will then select the relevant order from their table's order list: this will trigger a call from Dojo to retrieve the details of that specific order from the POS before attempting to record the payment, ensuring that the amount and other details are up to date. ## Step 3: Dojo creates a Payment Intent and authorises the payment > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-post-record-order-payment > See OpenAPI spec for RecordOrderPaymentByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-RecordOrderPaymentByIdV1_Request **Main page**: [RecordOrderPaymentById](https://docs.dojo.tech/core-concepts/orders#record-order-payment) Once the correct order has been selected by the customer, Dojo will create a Payment Intent and initiate the checkout flow for the customer to capture payment. Dojo will now capture the pre-authorised payment. Once captured, Dojo will use a RecordOrderPaymentById request containing the relevant `orderId` to inform the POS that the payment is captured. A `paymentIntentId` will be included in this request which should be recorded and can be used for retrieving payment details such as receipt data upon payment completion. The POS should respond to this request with a 200 response to indicate that the payment has been acknowledged and recorded. The POS should also respond with the current order "status" to show any changes that may have occurred to this attribute. If the payment cannot be recorded, such as in the event of a mismatching value being submitted in the RecordOrderPaymentById request, the POS should reject the request with a `409` error and the relevant `errorType`, for example: "Conflict". This will trigger a payment reversal on the customer app and prompt the user to reattempt the payment. **Note**: The POS may receive multiple RecordOrderPaymentById requests from different iniating customers, such as in the instance of a table of guests paying for their own individual items, and therefore should be prepared to see multiple requests. ## Step 4: Dojo displays updated order status to customer After receiving a successful response from the POS to the RecordOrderPaymentById request, Dojo will inform the customer of the outcome and given order status through the **Order and Pay** customer interface. --- ## Areas The **Area** entity represents physical areas within a location. Examples of areas would be "dining area", "beer garden" and "upstairs". ## Capabilities In the Dojo EPOS Data API, **capabilities** represent specific actions that the POS system can perform. These capabilities are linked to corresponding API endpoints in the POS system. By defining these capabilities, the POS system communicates to Dojo which features are supported and accessible. See [Registering capabilities](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities) for how each capability is registered with Dojo. **Registering a capability:** the heading for each capability below (for example `SearchOrders`, `GetOrderById`, `CreateOrderLock`, `RecordOrderPaymentById`) is the exact `name` value to send in the body of `PUT /epos/integrations/rest` or `PUT /epos/integrations/ws`. The version is sent alongside as a separate field (`"version": "v1"`); appending `V1` to the heading gives you the wire-level method Dojo invokes after registration (for example `RecordOrderPaymentByIdV1`). See [Registering capabilities](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities) for the full body schema. For backwards compatibility, registration also accepts the four legacy names `GetOrderBill`, `RecordOrderPayment`, `UpdatePartyById`, and `UpdateReservationById` — they are equivalent to `GetOrderBillById`, `RecordOrderPaymentById`, `UpdateParty`, and `UpdateReservation` respectively. New integrations should prefer the wire-aligned form shown in the headings below. ### ListAreas > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/epos-data/api#tag/Areas/operation/v1-list-areas > See OpenAPI spec for ListAreasV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-ListAreasV1_Request This capability enables listing areas from the POS system. --- ## Dojo Events Dojo Events are notifications about changes relating to entities which are owned by the Dojo API and allow a POS system to be able to react in near real time. These events are sent by Dojo with *at-least-once* semantics to a POS system, via the **HandleEvent** capability ([REST](https://docs.dojo.tech/epos-data/api/#tag/Events/paths/~1v1~1events/post) or [WS `HandleEventV1`](https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-HandleEventV1_Request)). An event payload contains a unique event `id`, the `accountId` specific to the location for whom the event is intended, when the event was `createdAt`, the event type in `event`, and `data` about the event. The Dojo Events API will always differentiate between the states of an entity, such as being created or updated. When an entity is created by Dojo, a **created** event will be sent, and when that entity is updated, a **status_updated** event will be sent. The difference between these events and [POS Events](https://docs.dojo.tech/core-concepts/pos-events) is that these events pertain to entities owned by **Dojo** and are sent from **Dojo** to the **POS system**. In contrast, [POS Events](https://docs.dojo.tech/core-concepts/pos-events) pertain to entities owned by the **POS system** and are sent from the **POS system** to **Dojo** Dojo Events function similar semantically to [Webhooks](https://docs.dojo.tech/development-resources/webhooks) in payload and functionality; If both the capability and webhook for an event are registered, that event will need to be handled idempotently as per the principle of *at-least-once*, as it will be sent by Dojo twice. ## Event Types Below is information about the various event types that can be sent by Dojo to the POS system, including why Dojo sends it, the data it holds, and links to the relevant entity documentation. | **Event Type** | **Description** | **Data** | | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------| | `payment_intent.created` | Whenever a **[Payment Intent](https://docs.dojo.tech/payments/manage-payments/payment-intent)** is created, this will trigger when a payment is prepared to be taken using a Dojo Product or if one is created through an [API Request](https://docs.dojo.tech/api/#tag/Payment-intents/operation/PaymentIntents_CreatePaymentIntent) |`paymentIntentId``paymentStatus``captureMode` | | `payment_intent.status_updated` | Whenever a **[Payment Intent](https://docs.dojo.tech/payments/manage-payments/payment-intent)** is updated, this will trigger when the status of a payment intent changes, such as being Captured or Cancelled. |`paymentIntentId``paymentStatus``captureMode`| ## Capabilities In the Dojo EPOS Data API, **capabilities** represent specific actions that the POS system can perform. These capabilities are linked to corresponding API endpoints in the POS system. By defining these capabilities, the POS system communicates to Dojo which features are supported and accessible. See [Registering capabilities](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities) for how each capability is registered with Dojo. **Registering a capability:** the heading for each capability below (for example `SearchOrders`, `GetOrderById`, `CreateOrderLock`, `RecordOrderPaymentById`) is the exact `name` value to send in the body of `PUT /epos/integrations/rest` or `PUT /epos/integrations/ws`. The version is sent alongside as a separate field (`"version": "v1"`); appending `V1` to the heading gives you the wire-level method Dojo invokes after registration (for example `RecordOrderPaymentByIdV1`). See [Registering capabilities](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities) for the full body schema. For backwards compatibility, registration also accepts the four legacy names `GetOrderBill`, `RecordOrderPayment`, `UpdatePartyById`, and `UpdateReservationById` — they are equivalent to `GetOrderBillById`, `RecordOrderPaymentById`, `UpdateParty`, and `UpdateReservation` respectively. New integrations should prefer the wire-aligned form shown in the headings below. ### HandleEvent:payment_intent.created > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Events/paths/~1v1~1events/post > See OpenAPI spec for HandleEventV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-HandleEventV1_Request This capability enables the POS system to begin recording payments against **[orders](https://docs.dojo.tech/core-concepts/orders)** taken by Dojo products. ### HandleEvent:payment_intent.status_updated > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Events/paths/~1v1~1events/post > See OpenAPI spec for HandleEventV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-HandleEventV1_Request This capability enables the POS system to record status updates on payments against **[orders](https://docs.dojo.tech/core-concepts/orders)** taken by Dojo products. --- ## POS Events POS Events are notifications about changes relating to entities which are owned by the POS system and allow Dojo products to be able to react in near real time. These events are sent by the POS system to Dojo via the [submit event](https://docs.dojo.tech/api/#tag/Events/paths/~1epos~1events/post) endpoint in the Dojo API. Each event payload only contains the `eventType` and the entity `id`, this minimal simple model has been chosen for the following reasons: - Simplifies the implementation of sending events about entities whenever they are updated on the POS system. - Reduces the risk of events with outdated data being processed by Dojo, instead Dojo will fetch the latest version of an entity via the relevant capability if required. The POS Events API does not differentiate between created and updated events, as Dojo products do not require this distinction. When an entity is created on the POS system, an **updated** event is expected to be sent. In cases where an entity is deleted/cleared from the POS system an updated event should also be triggered. When a Dojo product attempts to fetch an entity and receives a **not found** error, the product will assume that the entity no longer exists on the POS system. The difference between these events and [Dojo Events](https://docs.dojo.tech/core-concepts/dojo-events) is that these events pertain to entities owned by the **POS system** and are sent from the **POS system** to **Dojo**. In contrast, [Dojo Events](https://docs.dojo.tech/core-concepts/dojo-events) pertain to entities owned by **Dojo** and are sent from **Dojo** to the **POS system**. ## Event Types Below is information about the various event types that can be sent by the POS system to Dojo, including when it is expected to be sent by the POS system, and links to the relevant entity documentation. | **Event Type** | **Description** | | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `OrderUpdated` | Whenever an **[order](https://docs.dojo.tech/core-concepts/orders)** on the POS system is created or changed, a change could be due to adding/removing `items` on the [order](https://docs.dojo.tech/core-concepts/parties), changing the price or quantity of an item, or auxiliary information such as the `note` on an order changing. Dojo expects to receive this event as different products may require up to date information. | | `PartyUpdated` | Whenever a **[party](https://docs.dojo.tech/core-concepts/parties)** on the POS system is created or changed, a change could be due to the `status` of the [party](https://docs.dojo.tech/core-concepts/parties) changing if they were to leave the venue or changed `hostNotes` after a waiter records information about the [party](https://docs.dojo.tech/core-concepts/parties). | | `ReservationUpdated` | Whenever a **reservation** on the POS system is created or changed, a change could be due to the `startTime`/`endTime` of a reservation being updated or the assigned `tableIds` being changed due to a different reservation requiring one of the tables. | ## API ### Submit Event > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api/#tag/Events/paths/~1epos~1events/post This allows a POS system to send events via the Dojo API, more information about getting started with the Dojo API can be found [here](https://docs.dojo.tech/payments/getting-started). --- ## Orders The Order entity represents the core component of the Ordering API, containing all relevant information about an order placed by customers at a given location. An order can consist of multiple items, each with details like status, quantity, price, and applied modifiers. Dojo products create, modify and retrieve orders on the POS via the EPOS Data component of the Dojo API, these [capabilities](https://docs.dojo.tech/bookings/step-by-step-guide#capabilities) are documented below. ### Status The **Order Status** represents the various stages in an order’s lifecycle. As an order progresses from creation to fulfilment, its status will update to reflect its current state. | **Status** | **Description** | | --- | --- | | `New` | The order has been created but has not yet been processed. | | `Submitted` | The order has been submitted to the EPOS and is awaiting confirmation. | | `Confirmed` | The order has been confirmed by the EPOS and is awaiting kitchen or staff to accept. | | `Accepted` | The order has been accepted by the kitchen or staff for preparation. | | `Preparing` | The items in the order are currently being prepared. | | `Prepared` | The items have been fully prepared and are ready for service or collection. | | `Ready` | The order is ready for delivery or collection by the customer. | | `Finalized` | The order has been completed and paid for, and no further changes can be made. | | `Canceled` | The order has been canceled and is no longer active. | | `Failed` | The order has encountered an error and failed to process. This may require further investigation. | These statuses help track the state of each order and ensure that any integrated systems can react to updates in a consistent manner. ## Capabilities In the Dojo EPOS Data API, **capabilities** represent specific actions that the POS system can perform. These capabilities are linked to corresponding API endpoints in the POS system. By defining these capabilities, the POS system communicates to Dojo which features are supported and accessible. See [Registering capabilities](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities) for how each capability is registered with Dojo. **Registering a capability:** the heading for each capability below (for example `SearchOrders`, `GetOrderById`, `CreateOrderLock`, `RecordOrderPaymentById`) is the exact `name` value to send in the body of `PUT /epos/integrations/rest` or `PUT /epos/integrations/ws`. The version is sent alongside as a separate field (`"version": "v1"`); appending `V1` to the heading gives you the wire-level method Dojo invokes after registration (for example `RecordOrderPaymentByIdV1`). See [Registering capabilities](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities) for the full body schema. For backwards compatibility, registration also accepts the four legacy names `GetOrderBill`, `RecordOrderPayment`, `UpdatePartyById`, and `UpdateReservationById` — they are equivalent to `GetOrderBillById`, `RecordOrderPaymentById`, `UpdateParty`, and `UpdateReservation` respectively. New integrations should prefer the wire-aligned form shown in the headings below. ### CreateOrder > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-post-orders > See OpenAPI spec for CreateOrderV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-CreateOrderV1_Request This capability allows the creation of new orders within the POS system. It is essential for handling customer orders and storing relevant order details. ### GetOrderById > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-get-orders-orderId > See OpenAPI spec for GetOrderByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-GetOrderByIdV1_Request This capability enables Dojo to retrieve detailed information about a specific order using its unique order ID. This is crucial for order tracking and status updates. ### CancelOrderById > See OpenAPI spec for DELETE endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-delete-orders-orderId > See OpenAPI spec for CancelOrderByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-CancelOrderByIdV1_Request This capability provides the ability to cancel an order within the POS system, preventing further modifications or processing. Cancellations are performed using the order’s unique ID. The POS system can reject a `CancelOrder` reqeuest if the order is not in a state where it can be cancelled. ### SearchOrders > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/paths/~1v1~1orders~1search/post > See OpenAPI spec for SearchOrdersV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-SearchOrdersV1_Request This capability enables searching for orders based on various criteria. It supports filtering and pagination to help Dojo products efficiently find orders within the POS system. Each Dojo product has different requirements on what filters must be implemented which can be found on the product documentation page(s). ### RecordOrderPaymentById > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-post-record-order-payment > See OpenAPI spec for RecordOrderPaymentByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-RecordOrderPaymentByIdV1_Request This capability allows Dojo to record a payment against an order. All payments recorded this way will be sent with their `paymentIntentId` which is unique and can be used for both deduplication and to control the lifecycle of the payment with operations like Get and Reversal. ### CreateOrderLock > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-post-order-lock > See OpenAPI spec for CreateOrderLockV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-CreateOrderLockV1_Request This capability allows Dojo to acquire a lock on orders before making modifications to it like recording payments or adding items. These locks allow the EPOS to know when an Order being modified and give Dojo the guarantee that the Order will not be modified externally while these operations are taking place. Dojo will only try to acquire when making modifications, for other purposes fetching an eventually consistent snapshot of an Order from the EPOS through GetOrder should always be possible. | Registered capabilities | Behaviour | | -------- | ------- | | RecordOrderPaymentById | Dojo will send the RecordOrderPaymentById request, if a Conflict error is returned Dojo will attempt to reverse the payment | | RecordOrderPaymentById, CreateOrderLock, DeleteOrderLock | Dojo will first try to create the order lock with a long expiry. If successful it will try to record one or multiple payments then delete the lock. | | RecordOrderPaymentById, CreateOrderLock, DeleteOrderLock, ExtendOrderLock | Dojo will first try to create the order lock with a short expiry. If successful it will try to record one or multiple payments. If the payment session takes longer, it will extend the lock. After the payment session has finished we will delete the lock. | ### DeleteOrderLock > See OpenAPI spec for DELETE endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-delete-order-lock > See OpenAPI spec for DeleteOrderLockV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-DeleteOrderLockV1_Request This capability allows Dojo to release a lock on orders. If both this and CreateOrderLockRequest are registered then Dojo will only attempt to RecordOrderPaymentById against an order after having successfully acquired a lock and will release the lock once the payment is recorded. ### ExtendOrderLock > See OpenAPI spec for PUT endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-put-extend-order-lock > See OpenAPI spec for ExtendOrderLockV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-ExtendOrderLockV1_Request This capability allows Dojo to extend an existing lock. It is not required for the locking flow to function, registering this will allow Dojo to create locks with a shorter initial expiry and extend as needed. ### GetOrderBillById > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-get-order-bill > See OpenAPI spec for GetOrderBillByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-GetOrderBillByIdV1_Request This capability allows the terminal to request a Bill - a printable version of the Order. The EPOS can customise the fields and layout of the Bill on a per request basis. --- ## Parties The **Parties** entity represents a group seated in the venue, and should uniquely identify them in the POS for the entire duration of their stay. **Dojo Bookings** infers availability by the presence of a party at a table. Each party can include additional details such as deposits, special requests and allergen information. ## Capabilities In the Dojo EPOS Data API, **capabilities** represent specific actions that the POS system can perform. These capabilities are linked to corresponding API endpoints in the POS system. By defining these capabilities, the POS system communicates to Dojo which features are supported and accessible. See [Registering capabilities](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities) for how each capability is registered with Dojo. **Registering a capability:** the heading for each capability below (for example `SearchOrders`, `GetOrderById`, `CreateOrderLock`, `RecordOrderPaymentById`) is the exact `name` value to send in the body of `PUT /epos/integrations/rest` or `PUT /epos/integrations/ws`. The version is sent alongside as a separate field (`"version": "v1"`); appending `V1` to the heading gives you the wire-level method Dojo invokes after registration (for example `RecordOrderPaymentByIdV1`). See [Registering capabilities](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities) for the full body schema. For backwards compatibility, registration also accepts the four legacy names `GetOrderBill`, `RecordOrderPayment`, `UpdatePartyById`, and `UpdateReservationById` — they are equivalent to `GetOrderBillById`, `RecordOrderPaymentById`, `UpdateParty`, and `UpdateReservation` respectively. New integrations should prefer the wire-aligned form shown in the headings below. ### CreateParty > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Parties > See OpenAPI spec for CreatePartyV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-CreatePartyV1_Request This capability allows the creation of a new **Party** within the POS system. It is essential for assigning parties to a table and storing relevant order details. ### GetPartyById > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/epos-data/api#tag/Parties/operation/v1-get-parties-partyId > See OpenAPI spec for GetPartyByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-GetPartyByIdV1_Request This capability allows Dojo to retrieve up-to-date information about a specific **party** seated at a table, such as the unique ID, table ID and status. ### UpdateParty > See OpenAPI spec for PUT endpoint details: https://docs.dojo.tech/epos-data/api#tag/Parties/operation/v1-put-parties-partyId > See OpenAPI spec for UpdatePartyV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-UpdatePartyV1_Request This capability allows Dojo to update the POS with additional **party** information given after initial booking. For example, this could be the party's allergen requirements in the form of guestRequests, a change in booking time or a new expected end-time. ### DeletePartyById > See OpenAPI spec for DELETE endpoint details: https://docs.dojo.tech/epos-data/api#tag/Parties/operation/v1-delete-parties-partyId > See OpenAPI spec for DeletePartyByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-DeletePartyByIdV1_Request This capability allows Dojos Epos Data API to delete a specific **party** by using the party Id. ### SearchParties > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Parties/operation/v1-search-parties > See OpenAPI spec for SearchPartiesV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-SearchPartiesV1_Request This capability allows Dojo to retrieve parties from a POS. By default, the POS should not return parties where `endTime` is set, including them only where `completedOnly` is "true". --- ## Reservations The **Reservation** entity represents an upcoming party or booking. Reservations may be created, updated and deleted by Dojo products. Once a reservation has been seated within the venue, it becomes a [party](https://docs.dojo.tech/core-concepts/parties). ## Capabilities In the Dojo EPOS Data API, **capabilities** represent specific actions that the POS system can perform. These capabilities are linked to corresponding API endpoints in the POS system. By defining these capabilities, the POS system communicates to Dojo which features are supported and accessible. See [Registering capabilities](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities) for how each capability is registered with Dojo. **Registering a capability:** the heading for each capability below (for example `SearchOrders`, `GetOrderById`, `CreateOrderLock`, `RecordOrderPaymentById`) is the exact `name` value to send in the body of `PUT /epos/integrations/rest` or `PUT /epos/integrations/ws`. The version is sent alongside as a separate field (`"version": "v1"`); appending `V1` to the heading gives you the wire-level method Dojo invokes after registration (for example `RecordOrderPaymentByIdV1`). See [Registering capabilities](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities) for the full body schema. For backwards compatibility, registration also accepts the four legacy names `GetOrderBill`, `RecordOrderPayment`, `UpdatePartyById`, and `UpdateReservationById` — they are equivalent to `GetOrderBillById`, `RecordOrderPaymentById`, `UpdateParty`, and `UpdateReservation` respectively. New integrations should prefer the wire-aligned form shown in the headings below. ### CreateReservation > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Reservations > See OpenAPI spec for CreateReservationV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-CreateReservationV1_Request This capability allows for the creation of a new **reservation** within the POS system. This enables the creation of bookings on the POS by Dojo products. ### GetReservationById > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/epos-data/api#tag/Reservations/operation/v1-get-reservations-reservationId > See OpenAPI spec for GetReservationByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-GetReservationByIdV1_Request This capability allows Dojo to retrieve up-to-date information from the POS about a specific **reservation** such as the start-time, end-time and any booked table IDs. ### UpdateReservation > See OpenAPI spec for PUT endpoint details: https://docs.dojo.tech/epos-data/api#tag/Reservations/operation/v1-put-reservations-reservationId > See OpenAPI spec for UpdateReservationV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-UpdateReservationV1_Request This capability allows Dojo to update **reservations** on the POS. For example, this could be changes to the reservation's covers, time-slot or table IDs. ### DeleteReservationById > See OpenAPI spec for DELETE endpoint details: https://docs.dojo.tech/epos-data/api#tag/Reservations/operation/v1-delete-reservations-reservationId > See OpenAPI spec for DeleteReservationByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-DeleteReservationByIdV1_Request This capability allows Dojos to delete a specific **reservation** by using the reservation Id. ### SearchReservations > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Reservations/operation/v1-search-reservations > See OpenAPI spec for SearchReservationsV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-SearchReservationsV1_Request This capability allows Dojo to retrieve **reservations** from a POS and can include filters such as table Id and time slot. --- ## Tables The Table entity represents a physical place within a location and/or area where customers are designated. Tables are mostly static, but expected to change if there are physical layout changes at a location. Tables may have multiple active [orders](https://docs.dojo.tech/core-concepts/orders) and/or [parties](https://docs.dojo.tech/core-concepts/parties) sitting at them at any one time. ## Capabilities In the Dojo EPOS Data API, **capabilities** represent specific actions that the POS system can perform. These capabilities are linked to corresponding API endpoints in the POS system. By defining these capabilities, the POS system communicates to Dojo which features are supported and accessible. See [Registering capabilities](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities) for how each capability is registered with Dojo. **Registering a capability:** the heading for each capability below (for example `SearchOrders`, `GetOrderById`, `CreateOrderLock`, `RecordOrderPaymentById`) is the exact `name` value to send in the body of `PUT /epos/integrations/rest` or `PUT /epos/integrations/ws`. The version is sent alongside as a separate field (`"version": "v1"`); appending `V1` to the heading gives you the wire-level method Dojo invokes after registration (for example `RecordOrderPaymentByIdV1`). See [Registering capabilities](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities) for the full body schema. For backwards compatibility, registration also accepts the four legacy names `GetOrderBill`, `RecordOrderPayment`, `UpdatePartyById`, and `UpdateReservationById` — they are equivalent to `GetOrderBillById`, `RecordOrderPaymentById`, `UpdateParty`, and `UpdateReservation` respectively. New integrations should prefer the wire-aligned form shown in the headings below. ### SearchTables > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Tables/operation/v1-search-tables > See OpenAPI spec for SearchTablesV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-SearchTablesV1_Request This capability enables searching for Tables from the POS system. --- ## Terminal Sessions [Terminal sessions](https://docs.dojo.tech/payments/accept-payments/in-person-payments/pay-at-counter/terminals/create-session) allow you to establish a connection with the terminal (via the Dojo API) and prepare it for processing payments. The terminal session will update its [notification events](https://docs.dojo.tech/api#tag/Terminal-sessions/operation/TerminalSession_Create) throughout its lifecycle which can be displayed to the POS user. > **Tip:** Both **Sale** and **Matched Refund** require a [payment intent](https://docs.dojo.tech/api#tag/Payment-intents) to be created and passed in the request body, where an **Unlinked Refund** is not linked to a previous captured sale and can be initiated without. ### Status The **Terminal Session Status** represents the various stages in a terminal session lifecycle. As a **Terminal Session** progresses from creation to fulfilment, its status will update to reflect its current state. | **Status** | **Description** | | --- | --- | | `InitiateRequested` | The request to begin the session has been submitted to the Terminal and is awaiting confirmation. | | `Initiated` | The session has been confirmed by the Terminal and is awaiting payment to be taken. | | `Authorized` | The payment has been authorized pending [final capture](https://docs.dojo.tech/payments/manage-payments/capture) (Pre-authorization). | | `Captured` | Payment has now been captured and no further updates will be made to the session. | | `CancelRequested` | The request to cancel the session has been submitted to the Terminal and is awaiting confirmation. | | `Canceled` | The session has been canceled by the Terminal. | | `SignatureVerificationRequired` | Payment has been captured pending [signature verification](https://docs.dojo.tech/api#tag/Terminal-sessions/operation/TerminalSession_Signature). | | `SignatureVerificationAccepted` | Payment has been captured after successful signature verification [signature verification](https://docs.dojo.tech/api#tag/Terminal-sessions/operation/TerminalSession_Signature). | | `SignatureVerificationRejected` | Payment has been reversed following rejection of [signature verification](https://docs.dojo.tech/api#tag/Terminal-sessions/operation/TerminalSession_Signature).| | `Expired` | The terminal session has expired. | | `Declined` | Payment has been declined by the card issuer. | These statuses help track the state of each session and ensure that any integrated systems can react to updates in a consistent manner. --- ## Optional configurations >Learn how to activate additional features for your checkout screen. You can activate additional, optional features in your integration. The following table shows which fields are configurable in mobile SDK and web integration. |**Configurations**| **Mobile** | **Web**| |-----|---------|---------| |`customerEmail`| ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | |`billingAddress`| ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircleOneStar.svg#gh-light-mode-only) ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircleOneStarDarkMode.svg#gh-dark-mode-only)| ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg)| |`shippingAddress`| ![no](https://docs.dojo.tech/images/dojo-icons-small/XCircle.svg) | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg)| |`Wallet`| ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) |`itemLines`| ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) |`taxLines`| ![no](https://docs.dojo.tech/images/dojo-icons-small/XCircle.svg) | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) |`companyName`| ![no](https://docs.dojo.tech/images/dojo-icons-small/XCircle.svg) | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg)| *   Currently limited to Postcode and Country only. ## Configurations ​ The mobile SDK UI can do the following: - [**Add payment methods**](https://docs.dojo.tech/bookings/step-by-step-guide#add-payment-methods) Integrate Google Pay wallets in addition to card payments. - [**Collect billing address and user email**](https://docs.dojo.tech/bookings/step-by-step-guide#collect-billing-address-and-user-email) Use your checkout screen to capture useful information about your mobile app user. - [**Show detailed information about the order**](https://docs.dojo.tech/bookings/step-by-step-guide#show-detailed-information-about-the-order) Set up the information that you want to show to your mobile app users. ## Add payment methods ![Add payment methods](https://docs.dojo.tech/images/add-payment-methods-android.png) By default, the checkout page only supports card payments. To enable Google Pay wallet, you must first [configure Google Pay](https://docs.dojo.tech/bookings/android-setup-google-pay). Then, pass `"Card","Wallet"` in `paymentMethods`. For example: ​ ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' \ --data '{ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order-0001", "paymentMethods": [ "Card", "Wallet" ] }' ``` ## Collect billing address and user email ​ ![](https://docs.dojo.tech/images/billing-and-shipping-details-android.png) ​ You can add a form to collect the billing address and user email to the checkout screen by passing `collectionRequired: true` in `config.billingAddress`, and `config.customerEmail`. For example: ​ ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_kqCwRaWEsl9OM0xNSxh00eayT9k8hAqURGeNQseeV62rMxO5ZiZHub0-XRqkzPLfES2fVUl0seMOyujCIiYaMTaDyiBPf25b7W3Gr3oE0qbpTeM4MRuUMgtDt_scAEfJdqYBlBB_gt_31Bw7FihTISp2WIXXGeTD5WbwhdIhraIJVWR7jo2Hy-xKlBpK-lE8' \ --header 'Version: 2024-02-05' \ --data '{ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order-0001", "config": { "customerEmail": { "collectionRequired": true }, "billingAddress": { "collectionRequired": true } } }' ``` ## Show detailed information about the order ​ ![](https://docs.dojo.tech/images/show-detailed-information-android.png) ​ You can add information about each position in the order to the checkout page. Pass this data to `itemLines`. The `itemLines` amounts are independent of the payment intent amount. ​ ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents \ --header 'content-type: application/json' \ --header 'authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'version: 2024-02-05' \ --data '{ "amount": { "value": 4000, "currencyCode": "GBP" }, "reference": "Order-0001", "itemLines": [ { "id": "item 1", "caption": "Baseball hat", "amountTotal": { "value": 1200, "currencyCode": "GBP" } }, { "id": "item 2", "caption": "Baseball ball", "amountTotal": { "value": 350, "currencyCode": "GBP" } }, { "id": "item 3", "caption": "Baseball bat", "amountTotal": { "value": 2500, "currencyCode": "GBP" } } ] }' ``` --- ## Save card > Learn how to enable save card functionality for later use. You can provide your mobile app users with the ability to save their card information securely for future use. This allows users to choose a preferred payment method, reducing their need to enter card information repeatedly. This is a nice-to-have, but optional feature for your app. The following gif is a demonstration of this feature in a mobile app. ## Enabling save card To enable save card functionality in your app, do the following: > **Info:** - Dojo understands that each app is built differently. The steps listed serve as a good reference to build this feature into your app. > - `user` and `customer` might be used interchangeably in this guide except for [`customer` API endpoints](https://docs.dojo.tech/api#tag/Customers). ![](https://docs.dojo.tech/images/save-card-new-part-1-android.png) ![](https://docs.dojo.tech/images/save-card-new-part-2-android.png) ## Step 1: Ensure you have a customer ID - If you don’t have a Dojo user to link to your backend user, [create a new one](https://docs.dojo.tech/api#tag/Customers/operation/Customers_Create) using POST [/customers](https://docs.dojo.tech/api#tag/Customers/operation/Customers_Create). - If you already have a `customerId`, retrieve it. > **Info:** - Don't create a new customer for each transaction. This avoids customers from accessing their saved cards. > > > ## Step 2: Authorize your app to retrieve customer’s saved cards > > For mobile SDK to retrieve information about saved cards for a specific user, you must create and pass a [customer secret](https://docs.dojo.tech/api#tag/Customers/operation/Customers_CreateCustomerSecret) using POST [/customers/{customerId}/create-secret](https://docs.dojo.tech/api#tag/Customers/operation/Customers_CreateCustomerSecret). > > **Info:** > - To create a customer `secret`, ensure you have a `customerId` from [step 1](https://docs.dojo.tech/bookings/step-by-step-guide#step-1-ensure-you-have-a-customer-id) and, your [API Key](https://docs.dojo.tech/development-resources/api-keys). > - You must always create a customer `secret` in your backend and then pass it to your app. > - Never store sensitive data such as API Keys inside your app. > - Customer `secret` is short-lived, hence Dojo recommends creating a new one each time your app might need to access stored payment methods. The following code samples demonstrate how to create a customer `secret`. ```bash title="create-customer-secret.sh" # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/customers/cust_sandbox_6g-HvPv6VkG_Q_PXCpJqmw/create-secret \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' ``` ## Step 3: Create a payment intent linked to the customerId When creating a payment intent, pass the `customerId` to the [payment intent](https://docs.dojo.tech/payments/manage-payments/payment-intent) request body. ```javascript "customer": { "customerId": "cust_sandbox_9WibJ2zeMU2C9gkRnDgs1g" } ``` ## Step 4: Initiate payment flow in the app Pass the `paymentIntentId` and customer `secret` to your app. Then, pass them to the SDK to start the checkout process. ```java title="create-customer-secret.java" // Get the PaymentHandler private final DojoPaymentFlowHandler dojoPaymentFlowHandler = DojoSDKDropInUI.INSTANCE.createUIPaymentHandler( this, ((dojoPaymentResult) -> { Toast.makeText(this, dojoPaymentResult.name(), Toast.LENGTH_LONG).show(); return Unit.INSTANCE; })); // On "Pay" tapped dojoPaymentFlowHandler.startPaymentFlow( new DojoPaymentFlowParams( "", "" // Customer secret key )); ``` ## Step 5: Receive payment status Once payment is completed, the app receives a notification with a numerical code representing the result. Visit the [status codes](https://docs.dojo.tech/payments/accept-payments/online-payments/components/configuration#status-code) reference for more information about what each code means. Additionally, your backend will receive a notification via [Webhook](https://docs.dojo.tech/development-resources/webhooks). --- ## Setup Google Pay >Compatible with Android 5.0 and later. With Google Pay in your application, you can allow users to securely pay with nearly all credit and debit cards. > **Info:** Users can see Google Pay as a payment method in the following scenarios: > - When using a device compatible with Google Pay. > - If a user is located in a region where Google Pay is available. > - If a user already has Google Pay set up on their device. To enable Google Pay in your app and start accepting payments, you must first set up the integration. To set up the integration, do the following: ![Enable Google Pay](https://docs.dojo.tech/images/setup-google-pay.png) 1. You must first enable the [Google Pay API](https://developers.google.com/pay/api/android/guides/setup) to use Google Pay. To do so, add the following snippet to ``: ```xml title="AndroidManifest.xml" ... ``` 2. Request a `gatewayMerchantId` from [Dojo](https://support.dojo.tech/hc/en-gb/requests/new). 3. Login to [Google Pay portal](https://pay.google.com/) and obtain your `Merchant Id`. 4. Upload screenshots of your app containing the checkout scenario to your Google Pay console for review. 5. After Google approves your app, pass the `gatewayMerchantId` and `Merchant Id` to the following code snippet: ```javascript title="capture-google-pay.js" const result = await startPaymentFlow({ intentId: "", gPayMerchantId: "", gPayGatewayMerchantId: "", gPayMerchantName: "" }); console.log(result); ``` ## Testing Google Pay The Google Pay [Test Card Suite](https://developers.google.com/pay/api/android/guides/resources/test-card-suite) allows you to test Google Pay without the need of adding real cards to Google accounts. To instantly view these cards in your Google Account TEST environment, join [Google's User Group](https://groups.google.com/g/googlepay-test-mode-stub-data) and all test cards will be automatically added to your account so you don't need to add them manually. --- ## Step-by-step guide(Accept-payments) > Learn how to accept payments in your Android app using our mobile SDK. This guide explains the process of integrating the checkout experience in your app. ## Checkout experience flow The following explains the flow of a user's journey in the checkout experience. > **Info:** - The term `user` used in this document refers to a customer trying to make a payment through your mobile application. > - This guide assumes you named the button on your checkout screen as **Checkout**. 1. A user visits your app and taps **Checkout**. 2. Your mobile app sends the user's purchase information to your backend, your backend sends this information to Dojo's backend to [create a payment intent](https://docs.dojo.tech/bookings/step-by-step-guide#step-1-create-a-payment-intent). 3. Your mobile app starts the checkout process using the mobile SDK. 4. The mobile SDK collects the user payment details, sends them to the Dojo backend, and presents a result screen to the user. The mobile SDK then notifies the hosting application of the [payment result](https://docs.dojo.tech/bookings/step-by-step-guide#result-codes). 5. Your backend receives a [webhook notification](https://docs.dojo.tech/bookings/step-by-step-guide#step-3-handle-post-payment-events) when the payment is completed. ![](https://docs.dojo.tech/images/flow-checkout-page-android.png) **Flow diagram: Flow Checkout Page Android** ```mermaid sequenceDiagram actor U as User participant SDK as dojo mobile SDK participant App as Merchant mobile app participant MB as Merchant backend participant DB as dojo backend U->>App: Taps Checkout App->>MB: Sends information about user purchases MB->>DB: POST /payment-intents DB-->>MB: Payment intent object MB-->>SDK: Payment intent Id SDK-->>U: Display prebuilt Checkout screen U->>SDK: Enters payment details and taps Pay SDK->>DB: Processes payment DB-->>SDK: Sends response with the payment result SDK-->>U: Displays the payment result SDK->>App: Notifies mobile app with the payment result DB->>MB: Sends webhooks ``` ## How to process a payment This is a step-by-step guide that demonstrates how to process payments with Dojo's backend and your backend into your mobile app using Dojo's mobile SDK. ### Before you start This guide contains the following steps: 1. [Create a payment intent](https://docs.dojo.tech/bookings/step-by-step-guide#step-1-create-a-payment-intent). 2. [Start the checkout process](https://docs.dojo.tech/bookings/step-by-step-guide#step-2-start-checkout-process). 3. [Handle post-payment events](https://docs.dojo.tech/bookings/step-by-step-guide#step-3-handle-post-payment-events). 4. [Test and go live](https://docs.dojo.tech/bookings/step-by-step-guide#step-4-test-and-go-live). ### Step 1. Create a payment intent With the checkout button in your app, call your backend and then call Dojo's backend endpoint to create a payment intent. To create a payment intent, the following parameters are required: - `amount`: This includes the currency and value, in minor units, for example, "1000" for 10.00 GBP. - `reference`: Your unique reference for the payment intent, like the *order number*. Here's an example of how to create a payment intent for 10 GBP on your backend: ```py title="server.py" from urllib import response from flask import Flask, jsonify, request, render_template app = Flask(__name__) @app.route('/checkout', methods=['GET', 'POST']) def hello(): # POST request if request.method == 'POST': print(request.get_json()) # parse as JSON conn = http.client.HTTPSConnection("api.dojo.tech") # call post payment-intent payload = json.dumps({ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order 245" }) headers = { 'Content-Type': "application/json", 'Version': "2024-02-05", 'Authorization': "Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ" # <-- Change to your secret key } conn.request("POST", "/payment-intents/", payload, headers) # handling the response from POST res = conn.getresponse() data = res.read() resp_data = {} resp_data['id'] = json.loads(data)["id"] json_data = json.dumps(resp_data) ``` See the [API reference](https://docs.dojo.tech/api#operation/PaymentIntents_CreatePaymentIntent) for a complete list of parameters that can be used for payment intent creation. For configurations that apply to our mobile SDK, go to [Configurations](https://docs.dojo.tech/bookings/android-optional-configurations). ### Step 2. Start checkout process Once you've created the payment intent, pass the payment intent ID to your payment flow code. > **Info:** To start the checkout process, ensure you have installed the [latest SDK](https://docs.dojo.tech/android-setup). ```java title="capture-card.java" // Get the PaymentHandler private final DojoPaymentFlowHandler dojoPaymentFlowHandler = DojoSDKDropInUI.INSTANCE.createUIPaymentHandler( this, ((dojoPaymentResult) -> { Toast.makeText(this, dojoPaymentResult.name(), Toast.LENGTH_LONG).show(); return Unit.INSTANCE; })); // On "Pay" tapped dojoPaymentFlowHandler.startPaymentFlow( new DojoPaymentFlowParams( "" )); ``` After the user fills in their payment information on the checkout screen, Dojo processes the payment and redirects the user to the result screen. The app receives a [result code](https://docs.dojo.tech/bookings/step-by-step-guide#result-codes). > **Info:** For additional configurations that apply to our mobile SDK, go to [configurations](https://docs.dojo.tech/bookings/android-optional-configurations). ### Step 3. Handle post-payment events ### Step 4. Test and go live Before going live, test your integration using the test card numbers: ## Result codes When you make a payment using an SDK integration, your app will receive a `result` code. Refer to the following result codes for more information. | Result code | Result |Description | |-------------|------------------------------|-----| | `0` | **Successful** |The transaction was successful.| | `3` | **Authorizing** | The card holder hasn't completed 3DS, this status will only be seen on the REST API.| | `4` | **Referred** | The card issuer has parked the transaction awaiting contact with the customer before proceeding to authorize or decline the transaction.| | `5` | **Declined** | The transaction was declined by the card issuer or acquiring bank.| | `20` | **Duplicate Transaction** | The transaction which was processed was a duplicate. Ensure each transaction has a unique `OrderId`.| | `30` | **Failed** | Error executing transaction.| | `400` | **Invalid Request** | The request has failed validation by our servers and the transaction hasn't been submitted to the gateway. Possible causes for this are invalid transaction type or other data in the request.| | `401` | **Issue with Access Token** | The access token being used isn't valid, the transaction hasn't been submitted to the gateway. This can be caused if the token has already been used or the 30 minute expiry time has elapsed.| | `404` | **No Access Token Supplied** | No access token has been supplied. Transaction hasn't been submitted to the gateway.| | `500` | **Internal Server Error** | There's been an error submitting the transaction, please check the REST API for the status of the transaction.| | `7770` | **SDK Internal Error** | There's a problem on the SDK side. Contact [Dojo](https://support.dojo.tech/hc/en-gb/requests/new) for more information.| --- --- ## UI customization > Learn how to customize the mobile SDK UI to blend seamlessly into your app. The mobile SDK comes with two default themes: To switch between these themes, pass a `DojoThemeSettings` object as a parameter when starting the payment flow. ```java title="ui-customization.java" // call this before u display the ui sdk on the screen private void configureDojoThemeSettings() { // you can override any value you for lightColorPalette LightColorPalette lightColorPalette = new LightColorPalette( "#DD000000" // primaryLabelTextColor ); // you can override any value for the darkColorPalette DarkColorPalette darkColorPalette = new DarkColorPalette( "#DD000000" // primaryLabelTextColor ); DojoThemeSettings dojoThemeSettings = new DojoThemeSettings( lightColorPalette, darkColorPalette, // set that one to true if you don't support dark mode false, // set that one to false if you want to hide dojo brand true ); DojoSDKDropInUI.INSTANCE.setDojoThemeSettings(dojoThemeSettings); } ``` ## Properties `DojoThemeSettings` contains multiple properties that you can set individually. |Property | Description | |------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |`primaryLabelTextColor`| Primary label color. | |`secondaryLabelTextColor` | Secondary label color. | |`headerTintColor`| Header text color. | |`headerButtonTintColor`| Color of header buttons like the `X` button. | |`primarySurfaceBackgroundColor`| Background color of the screen. | |`primaryCTAButtonActiveBackgroundColor`| Background color of primary button. | |`primaryCTAButtonActiveTextColor`| Font color of primary button. | |`primaryCTAButtonDisabledBackgroundColor`| Background color of disabled state of primary button (filled button). | |`primaryCTAButtonDisableTextColor`| Font color of disabled state of primary button. | |`secondaryCTAButtonActiveBorderColor`| Border color of the secondary button (button that's transparent and only has a border color). The background color is the same as current `primarySurfaceBackgroundColor` and can’t be changed. | |`secondaryCTAButtonActiveTextColor`| Font color of secondary button. | |`separatorColor`| Color of separator between header and the screen content. | |`errorTextColor`| Error message color. | |`loadingIndicatorColor`| Color of the animated loader on the initial loading screen. | |`inputFieldPlaceholderColor`| Input field placeholder color. | |`inputFieldBackgroundColor`| Input field background color. | |`inputFieldDefaultBorderColor`| Input field default border color when field isn't selected and not in the error state. | |`inputFieldSelectedBorderColor`| Input field border color when selected. | |`inputElementActiveTintColor`| Color of tick boxes and saved card selection circle when selected. | |`inputElementDefaultTintColor`| Color of tick boxes and saved card selection circle when not selected. | ## Illustrations The following images are illustrations of the items available for customization. ### Screen 1: Google Pay ### Screen 2: Saved card ### Screen 3: Input name, address, and email id ### Screen 4: Input screen with keypad --- ## Accept payments in Android >All you need to know about accepting payments on Android devices. [![](https://docs.dojo.tech/images/dojo-icons/BookBookmark.svg) **Step-by-step Guide** Guide to start accepting payments in your mobile app.](accept-payments/android-step-by-step-guide) [![](https://docs.dojo.tech/images/dojo-icons/AndroidLogo.svg) **Setup Google Pay** Guide to accept payments with Google Pay.](accept-payments/android-setup-google-pay) [![](https://docs.dojo.tech/images/dojo-icons/PaymentCard.svg) **Save Card for Later** Allow users to save their cards for later use. View complete flow and code samples.](accept-payments/android-save-card) [![](https://docs.dojo.tech/images/dojo-icons/Layout.svg) **Optional Configurations** Learn how to configure additional elements in your app.](accept-payments/android-optional-configurations) [![](https://docs.dojo.tech/images/dojo-icons/Code.svg) **UI Customization** Guide to create and customize payment screens and elements.](accept-payments/android-ui-customization) [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Need a hand?** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) --- ## Android integration >Learn more about integrating with Dojo's Android SDKs. - [**Accept payments from all major credit and debit cards**](https://docs.dojo.tech/bookings/android/android-accept-payments) Allow users to pay using a card that works best for them. - [**Accept Google Pay payments**](https://docs.dojo.tech/bookings/android/accept-payments/android-setup-google-pay) Integrate Google Pay to your checkout screen in addition to card payments. - [**Allow users to manage and save card information for future use**](https://docs.dojo.tech/bookings/android/accept-payments/android-save-card) Allow users to save card information for future payments. - [**Collect additional information from a user (like email, billing address)**](https://docs.dojo.tech/bookings/android/accept-payments/android-optional-configurations) Use your checkout screen to capture useful information about your customer. - [**Customize the UI of your checkout screen**](https://docs.dojo.tech/bookings/android/accept-payments/android-ui-customization) Choose the colors for the checkout screen UI that align with your brand's visual identity. ## Ready to get started? [![](https://docs.dojo.tech/images/dojo-icons/Wrench.svg) **Install SDK** Install the Dojo Android SDK to start accepting payments in mobile apps.](android/android-setup) --- ## Compatibility matrix > Learn which Compose file versions are compatible with the Dojo UI SDK. The following table shows which Compose file versions support our UI SDK versions. | Compose | Dojo UI SDK | | --------| ----------- | | 1.5.0 | 1.3.3 | | 1.4.x | 1.3.1 | --- ## Demo > Want to get your hands on a demo app before you begin your integration? The demo app is a ready-to-run example with the mobile SDK integrated. This allows you to play around with the mobile SDK features. This app is available on both [Kotlin](https://github.com/dojo-engineering/android-dojo-pay-sdk/blob/master/sample/src/main/java/tech/dojo/pay/sdksample/ExampleKotlin.kt) and [Java](https://github.com/dojo-engineering/android-dojo-pay-sdk/blob/master/sample/src/main/java/tech/dojo/pay/sdksample/ExampleJava.java) inside the [mobile SDK repository](https://github.com/dojo-engineering/android-dojo-pay-sdk). ## How to run the Demo app 1. Clone the [repository](https://github.com/dojo-engineering/android-dojo-pay-sdk). ```bash git clone git@github.com:dojo-engineering/android-dojo-pay-sdk.git ``` 2. Navigate to any of the following folders depending on the language: - [Kotlin](https://github.com/dojo-engineering/android-dojo-pay-sdk/tree/master/sample/src/main/java/tech/dojo/pay/sdksample) - [Java](https://github.com/dojo-engineering/android-dojo-pay-sdk/tree/master/sample/src/main/java/tech/dojo/pay/sdksample) ```bash cd sample/src/main/java/tech/dojo/pay/sdksample ``` 3. Navigate to `ExampleKotlin` or `ExampleJava` and replace `payment-intent-id` with a [`paymentIntentId`](https://docs.dojo.tech/bookings/accept-payments/android-step-by-step-guide) that you generated on your side. 5. Run the app and tap `startPaymentFlow` button on the screen. --- ## Setup > Learn how to setup the Dojo Android SDK. [![Releases](https://img.shields.io/github/v/tag/dojo-engineering/android-dojo-pay-sdk?logo=Github&labelColor)](https://github.com/dojo-engineering/android-dojo-pay-sdk/tags) ## Declare the repository Dojo hosts the Android SDK dependencies in a Maven repository. You can declare the Dojo Android SDK repository by adding the URL in the top-level `build.gradle` file. > **Info:** - The SDK uses an external library [Cardinal](https://www.cardinalcommerce.com/) to support 3DS. To get the credentials, contact [Dojo support](https://support.dojo.tech/hc/en-gb/requests/new). > - Ensure that you exclude payment-related fields from tracking if you are using screen recording or session recording services like **LogRocket** or **UXCam**. You can do that by setting `themeSettings.analyticsExcludedFieldsIdentifier` with your identifier value. ```java title="build.gradle" repositories { ... maven { url = uri("https://cardinalcommerceprod.jfrog.io/artifactory/android") credentials { // Contact Dojo support for credentials username = "" password = "" } } } ``` ## Add dependency To install the Dojo Android SDK, add `tech.dojo.pay` to [`dependencies`](https://developer.android.com/studio/build/dependencies) of your `app\build.gradle` file. ```java title="build.gradle" dependencies { ... implementation ("tech.dojo.pay:sdk:1.6.2") implementation ("tech.dojo.pay:uisdk:1.3.5") } ``` If your app supports [`ProGuard`](https://www.guardsquare.com/proguard), add the following dependency to your `proguard-rules.pro` file: ```java title="proguard-rules.pro" -keep class com.cardinalcommerce.dependencies.internal.bouncycastle.** -keep class com.cardinalcommerce.dependencies.internal.nimbusds.** -keep class tech.dojo.pay.** { *; } ``` --- [![](https://docs.dojo.tech/images/dojo-icons/BookBookmark.svg) **Releases** Details on the latest SDK changes and previous versions.](https://github.com/orgs/dojo-engineering/packages?repo_name=android-dojo-pay-sdk) --- ## Optional configurations(Accept-payments) >Learn how to activate additional features for your checkout screen. You can activate additional features like address collection. The following table shows which fields are configurable in mobile SDK integration and web integration. |**Configurations**| **Mobile** | **Web**| |-----|---------|---------| |`customerEmail`| ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | |`billingAddress`| ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircleOneStar.svg#gh-light-mode-only) ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircleOneStarDarkMode.svg#gh-dark-mode-only)| ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg)| |`shippingAddress`| ![no](https://docs.dojo.tech/images/dojo-icons-small/XCircle.svg) | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg)| |`Wallet`| ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) |`itemLines`| ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) |`taxLines`| ![no](https://docs.dojo.tech/images/dojo-icons-small/XCircle.svg) | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) |`companyName`| ![no](https://docs.dojo.tech/images/dojo-icons-small/XCircle.svg) | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg)| *   Currently limited to Postcode and Country only. ## Configurations ​ The mobile SDK UI can do the following: - [**Add payment methods**](https://docs.dojo.tech/bookings/step-by-step-guide#add-payment-methods) Integrate Apple Pay wallets in addition to card payments. - [**Collect billing address and user email**](https://docs.dojo.tech/bookings/step-by-step-guide#collect-billing-address-and-user-email) Use your checkout screen to capture useful information about your mobile app user. - [**Show detailed information about the order**](https://docs.dojo.tech/bookings/step-by-step-guide#show-detailed-information-about-the-order) Set up the information that you want to show to your mobile app users. ## Add payment methods ![Add payment methods](https://docs.dojo.tech/images/add-payment-methods-ios.png) By default, the checkout screen supports only card payments. To also enable the Apple Pay wallet, you must first [configure Apple Pay](https://docs.dojo.tech/bookings/ios-setup-apple-pay). Then pass `"Card", "Wallet"` in `paymentMethods` when you create a payment intent, for example: ​ ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' \ --data '{ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order-0001", "paymentMethods": [ "Card", "Wallet" ] }' ``` ## Collect billing address and user email ​ ![](https://docs.dojo.tech/images/billing-and-shipping-details-mobile.png) ​ You can add a form to collect the billing address and user email to the checkout screen. Pass `collectionRequired: true` in `config.billingAddress`, and `config.customerEmail`, for example: ​ ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_kqCwRaWEsl9OM0xNSxh00eayT9k8hAqURGeNQseeV62rMxO5ZiZHub0-XRqkzPLfES2fVUl0seMOyujCIiYaMTaDyiBPf25b7W3Gr3oE0qbpTeM4MRuUMgtDt_scAEfJdqYBlBB_gt_31Bw7FihTISp2WIXXGeTD5WbwhdIhraIJVWR7jo2Hy-xKlBpK-lE8' \ --header 'Version: 2024-02-05' \ --data '{ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order-0001", "config": { "customerEmail": { "collectionRequired": true }, "billingAddress": { "collectionRequired": true } } }' ``` ## Show detailed information about the order ​ ![](https://docs.dojo.tech/images/show-detailed-information-ios.png) ​ You can add information about each position in the order to the checkout page. Pass this data to `itemLines`. The `itemLines` amounts are independent of the payment intent amount. ​ ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents \ --header 'content-type: application/json' \ --header 'authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'version: 2024-02-05' \ --data '{ "amount": { "value": 4000, "currencyCode": "GBP" }, "reference": "Order-0001", "itemLines": [ { "id": "item 1", "caption": "Baseball hat", "amountTotal": { "value": 1200, "currencyCode": "GBP" } }, { "id": "item 2", "caption": "Baseball ball", "amountTotal": { "value": 350, "currencyCode": "GBP" } }, { "id": "item 3", "caption": "Baseball bat", "amountTotal": { "value": 2500, "currencyCode": "GBP" } } ] }' ``` --- ## Save card(Accept-payments) > Learn how to enable **Save Card** functionality for later use. You can provide your mobile app users with the ability to save their card information securely for future use. This allows users to set their preferred payment method, reducing the need to enter card information repeatedly. This is a nice-to-have feature in your app, however, this is optional. The following gif is a demonstration of this feature within a mobile app. ## Enabling Save Card To enable the **Save Card** functionality within your app, do the following: > **Info:** - Dojo understands that each app is built differently. The steps listed serve as a good reference to build this feature into your app. > - `user` and `customer` might be used interchangeably in this guide except for [`customer` API endpoints](https://docs.dojo.tech/api#tag/Customers). ![](https://docs.dojo.tech/images/save-card-new-part-1.png) ![](https://docs.dojo.tech/images/save-card-new-part-2.png) ## Step 1: Ensure you have a customer id - If you don’t have a Dojo user to link to your backend user, [create a new one](https://docs.dojo.tech/api#tag/Customers/operation/Customers_Create) using POST[/customers](https://docs.dojo.tech/api#tag/Customers/operation/Customers_Create). - If you already have a `customerId`, retrieve it. > **Info:** - Don't create a new customer for each transaction. This avoids customers from accessing their saved cards. > > > ## Step 2: Authorize your app to retrieve customer’s saved cards > > For mobile SDK to retrieve information about saved cards for a specific user, you must create and pass a [customer secret](https://docs.dojo.tech/api#tag/Customers/operation/Customers_CreateCustomerSecret) using POST [/customers/{customerId}/create-secret](https://docs.dojo.tech/api#tag/Customers/operation/Customers_CreateCustomerSecret). > > **Info:** > - To create a customer `secret`, ensure you have the `customerId` from [step 1](https://docs.dojo.tech/bookings/step-by-step-guide#step-1-ensure-you-have-a-customer-id) and your API Key. > - You must always create a customer `secret` in your backend and then pass it to your app. > - Never store sensitive data such as API Keys inside your app. > - Customer `secret` is short-lived, hence Dojo recommends creating a new one each time your app might need to access stored payment methods. The following code samples demonstrate how to create a customer `secret`. ```bash title="create-customer-secret.sh" # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/customers/cust_sandbox_6g-HvPv6VkG_Q_PXCpJqmw/create-secret \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' ``` ## Step 3: Create a payment intent linked to the customerId When creating a payment intent, pass the `customerId` to the payment intent request body. ```javascript "customer": { "customerId": "cust_sandbox_9WibJ2zeMU2C9gkRnDgs1g" } ``` ## Step 4: Initiate payment flow in the app Pass the `paymentIntentId` and customer `secret` to your app and then pass them to the mobile SDK to start the checkout process. ```swift title="create-customer-secret.swift" dojoUI.startPaymentFlow( paymentIntentId: "", controller: self, customerSecret: "" // Customer secret key ) { result in print(result) } ``` ## Step 5: Receive payment status Once payment is completed, the SDK gets a notification with a numerical code representing the result. Check out the [status codes](https://docs.dojo.tech/payments/accept-payments/online-payments/components/configuration#status-code) reference for more information about what each code means. Additionally, your backend will receive a notification via [Webhook](https://docs.dojo.tech/development-resources/webhooks). --- ## Setup Apple Pay >Compatible with iOS 11 and later. With Apple Pay in your application, you can allow users to securely pay with nearly all credit and debit cards. > **Info:** Users can see Apple Pay as a payment method in the following scenarios: > - When using a device compatible with Apple Pay. > - If a user is located in a region where Apple Pay is available. > - If a user already has Apple Pay set up on their device. To enable Apple Pay in your app and start accepting payments, you must first set up the integration. To setup the integration, do the following: ![Merchant Identifier](https://docs.dojo.tech/images/setup-apple-pay.png) 1. Create a new [Merchant ID](https://developer.apple.com/account/resources/identifiers/add/bundleId). For more details, see [Apple Developer Account Help](https://developer.apple.com/help/account/configure-app-capabilities/configure-apple-pay). 2. [Contact Dojo](https://support.dojo.tech/hc/en-gb/requests/new) for a `signing key`. 3. Generate a [payment processing certificate](https://developer.apple.com/account/resources/certificates/add) for the [Merchant ID](https://developer.apple.com/account/resources/identifiers/add/bundleId) you created using the `signing key`. To do so, go to the [Apple developer portal](https://developer.apple.com/account/resources/certificates/add) and under **Certificates, Identifiers, and Profiles** > **Create a New Certificate** > **Upload a Certificate Signing Request**, upload `CertificateSigningRequest.certSigningRequest` that you received from Dojo. 4. Download the payment processing certificate (with extension `.cer`) and send that certificate to [Dojo](https://support.dojo.tech/hc/en-gb/requests/new). 5. Using the following code, set the `merchantIdentifier` property with your [Merchant ID](https://developer.apple.com/account/resources/identifiers/add/bundleId) you created in Step 1. ```javascript title="capture-apple-pay.js" const result = await startPaymentFlow({ intentId: "", applePayMerchantId: "" }); console.log(result); ``` > **Info:** Known limitation: > Our SDK does not support Amex cards with Apple Pay. ## Testing Apple Pay To enable test cards for Apple Pay, you must have an [Apple Sandbox Tester Account](https://developer.apple.com/help/app-store-connect/test-in-app-purchases-main/create-sandbox-apple-ids/). This lets you add test cards to your Apple Wallet. See Apple's Sandbox Testing [Documentation](https://developer.apple.com/apple-pay/sandbox-testing/) to set up your Sandbox Tester Account and navigate to Test Cards for Apps and the Web to see the full list of supported test cards by Apple. --- ## Step-by-step guide(3) > Learn how to accept payments in your iOS app using our mobile SDK. This guide explains the process of integrating the checkout experience in your app. ## Checkout experience flow The following explains the flow of a user's journey in the checkout experience. > **Info:** - The term `user` used in this document refers to a customer trying to make a payment through your mobile application. > - This guide assumes you named the button on your checkout screen as **Checkout**. 1. A user visits your app and taps **Checkout**. 2. Your mobile app sends the user's purchase information to your backend, your backend sends this information to Dojo's backend to [create a payment intent](https://docs.dojo.tech/bookings/step-by-step-guide#step-1-create-a-payment-intent). 3. Your mobile app starts the checkout process using the mobile SDK. 4. The mobile SDK collects the user payment details, sends them to the Dojo backend, and presents a result screen to the user. The mobile SDK then notifies the hosting application of the [payment result](https://docs.dojo.tech/bookings/step-by-step-guide#result-code). 5. Your backend receives a [webhook notification](https://docs.dojo.tech/bookings/step-by-step-guide#step-3-handle-post-payment-events) when the payment is completed. ![](https://docs.dojo.tech/images/flow-checkout-page-ios.png) **Flow diagram: Flow Checkout Page Ios** ```mermaid sequenceDiagram actor U as User participant SDK as dojo mobile SDK participant App as Merchant mobile app participant MB as Merchant backend participant DB as dojo backend U->>App: Taps Checkout App->>MB: Sends information about user purchases MB->>DB: POST /payment-intents DB-->>MB: Payment intent object MB-->>SDK: Payment intent Id SDK-->>U: Display prebuilt Checkout screen U->>SDK: Enters payment details and taps Pay SDK->>DB: Processes payment DB-->>SDK: Sends response with the payment result SDK-->>U: Displays the payment result SDK->>App: Notifies mobile app with the payment result DB->>MB: Sends webhooks ``` ## How to process a payment This is a step-by-step guide that demonstrates how to process payments with Dojo's backend and your backend into your mobile app using Dojo's mobile SDK. ### Before you start This guide contains the following steps: 1. [Create a payment intent](https://docs.dojo.tech/bookings/step-by-step-guide#step-1-create-a-payment-intent). 2. [Start the checkout process](https://docs.dojo.tech/bookings/step-by-step-guide#step-2-start-checkout-process). 3. [Handle post-payment events](https://docs.dojo.tech/bookings/step-by-step-guide#step-3-handle-post-payment-events). 4. [Test and go live](https://docs.dojo.tech/bookings/step-by-step-guide#step-4-test-and-go-live). ### Step 1. Create a payment intent With the checkout button in your app, call your backend and then call Dojo's backend endpoint to create a payment intent. To create a payment intent, the following parameters are required: - `amount`: This includes the currency and value, in minor units, for example, "1000" for 10.00 GBP. - `reference`: Your unique reference for the payment intent, like the *order number*. Here's an example of how to create a payment intent for 10 GBP on your backend: ```py title="server.py" from urllib import response from flask import Flask, jsonify, request, render_template app = Flask(__name__) @app.route('/checkout', methods=['GET', 'POST']) def hello(): # POST request if request.method == 'POST': print(request.get_json()) # parse as JSON conn = http.client.HTTPSConnection("api.dojo.tech") # call post payment-intent payload = json.dumps({ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order 245" }) headers = { 'Content-Type': "application/json", 'Version': "2024-02-05", 'Authorization': "Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ" # <-- Change to your secret key } conn.request("POST", "/payment-intents/", payload, headers) # handling the response from POST res = conn.getresponse() data = res.read() resp_data = {} resp_data['id'] = json.loads(data)["id"] json_data = json.dumps(resp_data) ``` See the [API reference](https://docs.dojo.tech/api#operation/PaymentIntents_CreatePaymentIntent) for a complete list of parameters that can be used for payment intent creation. For configurations that apply to our mobile SDK, go to [Configurations](https://docs.dojo.tech/bookings/ios-optional-configurations). ### Step 2. Start checkout process Once you've created the payment intent, pass the payment intent ID to your payment flow code. > **Info:** To start the checkout process, ensure you have installed the [latest SDK](https://docs.dojo.tech/ios-setup). ```kotlin title="capture-card.swift" let dojoUI = DojoSDKDropInUI() dojoUI.startPaymentFlow(paymentIntentId: "", controller: self) { result in print(result) } ``` After the user fills in their payment information on the checkout screen, Dojo processes the payment and redirects the user to the result screen. Your app receives a [result code](https://docs.dojo.tech/bookings/step-by-step-guide#result-code). > **Info:** For additional configurations that apply to our mobile SDK, go to [configurations](https://docs.dojo.tech/bookings/ios-optional-configurations). ### Step 3. Handle post-payment events ### Step 4. Test and go live Before going live, test your integration using the test card numbers: ### Result code When you make a payment with using an SDK integration, your app will receive a `result` code. Refer to the following result codes for more information. | Result Code | Result |Description | |-----|------------------------------|-----| |`0` | **Successful** |The transaction was successful.| |`3` | **Authorizing** | The card holder hasn't completed 3DS, this status will only be seen on the REST API.| |`4` | **Referred** | The card issuer has parked the transaction awaiting contact with the customer before proceeding to authorize or decline the transaction.| |`5` | **Declined** | The transaction was declined by the card issuer or acquiring bank.| |`20` | **Duplicate Transaction** | The transaction which was processed was a duplicate. Ensure each transaction has a unique `OrderId`.| |`30` | **Failed** | Error executing transaction.| |`400` | **Invalid Request** | The request has failed validation by our servers and the transaction hasn't been submitted to the gateway. Possible causes for this are invalid transaction type or other data in the request.| |`401` | **Issue with Access Token** | The access token being used isn't valid, the transaction hasn't been submitted to the gateway. This can be caused if the token has already been used or the 30 minute expiry time has elapsed.| |`404` | **No Access Token Supplied** | No access token has been supplied. Transaction hasn't been submitted to the gateway.| |`500` | **Internal Server Error** | There's been an error submitting the transaction, please check the REST API for the status of the transaction.| |`7770` | **SDK Internal Error** | There's a problem on the SDK side. Contact [Dojo](https://support.dojo.tech/hc/en-gb/requests/new) for more information.| --- --- ## UI customization(Accept-payments) > Learn how to customize the mobile SDK UI to blend seamlessly into your app. The mobile SDK comes with two default themes: To switch between these themes, pass a `DojoThemeSettings` object as a parameter when starting a payment flow. ```kotlin title="ui-customization.swift" // Obtain an instance of the desired theme var lightTheme = DojoThemeSettings.getLightTheme() let darkTheme = DojoThemeSettings.getDarkTheme() // Set an individual property to a custom color lightTheme.primaryLabelTextColor = .red // Pass the desired theme to the SDK when starting the payment flow let dojoUI = DojoSDKDropInUI() dojoUI.startPaymentFlow(themeSettings: darkTheme) ``` ## Properties `DojoThemeSettings` contains multiple properties that you can set individually. |Property | Description | |------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |`primaryLabelTextColor`| Primary label color. | |`secondaryLabelTextColor` | Secondary label color. | |`headerTintColor`| Header text color. | |`headerButtonTintColor`| Color of header buttons like the `X` button. | |`primarySurfaceBackgroundColor`| Background color of the screen. | |`primaryCTAButtonActiveBackgroundColor`| Background color of primary button. | |`primaryCTAButtonActiveTextColor`| Font color of primary button. | |`primaryCTAButtonDisabledBackgroundColor`| Background color of disabled state of primary button (filled button). | |`primaryCTAButtonDisableTextColor`| Font color of disabled state of primary button. | |`secondaryCTAButtonActiveBorderColor`| Border color of the secondary button (button that's transparent and only has a border color). The background color is the same as current `primarySurfaceBackgroundColor` and can’t be changed. | |`secondaryCTAButtonActiveTextColor`| Font color of secondary button. | |`separatorColor`| Color of separator between header and the screen content. | |`errorTextColor`| Error message color. | |`loadingIndicatorColor`| Color of the animated loader on the initial loading screen. | |`inputFieldPlaceholderColor`| Input field placeholder color. | |`inputFieldBackgroundColor`| Input field background color. | |`inputFieldDefaultBorderColor`| Input field default border color when field isn't selected and not in the error state. | |`inputFieldSelectedBorderColor`| Input field border color when selected. | |`inputElementActiveTintColor`| Color of tick boxes and saved card selection circle when selected. | |`inputElementDefaultTintColor`| Color of tick boxes and saved card selection circle when not selected. | |`lightStyleForDefaultElements`| Switch between light and dark sets of graphic elements (like keypad, Apple Pay, card schema images). | ## Illustrations The following images are illustrations of the items available for customization. ### Screen 1: Apple Pay ### Screen 2: Saved card ### Screen 3: Input name, address, and email ### Screen 4: Input screen with keypad --- ## Accept payments in iOS >All you need to know about accepting payments on iOS devices. [![](https://docs.dojo.tech/images/dojo-icons/BookBookmark.svg) **Step-by-step Guide** Guide to start accepting payments in your mobile app.](accept-payments/ios-step-by-step-guide) [![](https://docs.dojo.tech/images/dojo-icons/AppleLogo.svg) **Setup Apple Pay** Guide to accept payments with Apple Pay.](accept-payments/ios-setup-apple-pay) [![](https://docs.dojo.tech/images/dojo-icons/PaymentCard.svg) **Save Card for Later** Allow users to save their cards for later use. View complete flow and code samples.](accept-payments/ios-save-card) [![](https://docs.dojo.tech/images/dojo-icons/Layout.svg) **Optional Configurations** Learn how to configure additional elements in your app.](accept-payments/ios-optional-configurations) [![](https://docs.dojo.tech/images/dojo-icons/Code.svg) **UI Customization** Guide to create and customize payment screens and elements.](accept-payments/ios-ui-customization) [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Need a hand?** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) --- ## Demo(Ios) > Want to get your hands on a demo app before you begin your integration? The demo app is a ready-to-run example with the mobile SDK integrated. This allows you to play around with the mobile SDK features. This app is available on both [Swift](https://github.com/dojo-engineering/dojo-ios-sdk-drop-in-ui/tree/main/ExampleSwift) and [Objective-C](https://github.com/dojo-engineering/dojo-ios-sdk-drop-in-ui/tree/main/ExampleObjc) inside the [mobile SDK repository](https://github.com/dojo-engineering/dojo-ios-sdk-drop-in-ui). > **Info:** To run the demo app, you need to have [CocoaPods](https://guides.cocoapods.org/using/getting-started.html) installed. ## How to run the Demo app 1. Clone the [repository](https://github.com/dojo-engineering/dojo-ios-sdk-drop-in-ui). ```bash git clone git@github.com:dojo-engineering/dojo-ios-sdk-drop-in-ui.git ``` 2. Navigate to any of the following folders depending on the language: - [ExampleSwift](https://github.com/dojo-engineering/dojo-ios-sdk-drop-in-ui/tree/main/ExampleSwift) - [ExampleObjc](https://github.com/dojo-engineering/dojo-ios-sdk-drop-in-ui/tree/main/ExampleObjc) ```bash cd dojo-ios-sdk-drop-in-ui/ExampleSwift ``` 3. Install the dependencies. ```bash pod install ``` 4. Open `dojo-ios-sdk-drop-in-ui.xcworkspace`. ```bash open dojo-ios-sdk-drop-in-ui.xcworkspace ``` 5. Navigate to `ViewController` and replace `payment-intent-id` with a [`paymentIntentId`](https://docs.dojo.tech/bookings/accept-payments/ios-step-by-step-guide) that you generated on your side. 6. Run the app and press `startPaymentFlow` button on the screen. --- ## iOS integration >Learn more about Dojo's iOS mobile SDKs. - [**Accept payments from all major credit and debit cards**](https://docs.dojo.tech/bookings/ios/ios-accept-payments) Allow users to pay using a card that works best for them. - [**Accept Apple Pay payments**](https://docs.dojo.tech/bookings/ios/accept-payments/ios-setup-apple-pay) Integrate Apple Pay to your checkout screen in addition to card payments. - [**Allow users to manage and save card information for future use**](https://docs.dojo.tech/bookings/ios/accept-payments/ios-save-card) Allow users to save card information for future payments. - [**Collect additional information from a user (like email, billing address)**](https://docs.dojo.tech/bookings/ios/accept-payments/ios-optional-configurations) Use your checkout screen to capture useful information about your customer. - [**Customize the UI of your checkout screen**](https://docs.dojo.tech/bookings/ios/accept-payments/ios-ui-customization) Choose the colors for the checkout screen UI that align with your brand's visual identity. ## Ready to get started? [![](https://docs.dojo.tech/images/dojo-icons/Wrench.svg) **Install SDK** Install the Dojo iOS SDK to start accepting payments in mobile apps.](ios/ios-setup) --- ## Setup(Ios) > Learn how to setup the Dojo iOS SDK. [![GitHub release](https://img.shields.io/github/v/release/dojo-engineering/dojo-ios-sdk-drop-in-ui?logo=Github&labelColor)](https://github.com/dojo-engineering/dojo-ios-sdk-drop-in-ui) The Dojo iOS SDK is available on [CocoaPods](https://cocoapods.org/) and [Swift Package Manager](https://www.swift.org/package-manager/). 1. Ensure you have the latest version of CocoaPods. 2. In your existing [Podfile](https://guides.cocoapods.org/syntax/podfile.html), add the following lines: ```ruby title="Podfile" pod 'dojo-ios-sdk-drop-in-ui', :git => 'git@github.com:dojo-engineering/dojo-ios-sdk-drop-in-ui.git', :tag => '1.3.2' pod 'dojo-ios-sdk', :git => 'git@github.com:Dojo-Engineering/dojo-ios-sdk.git', :tag => '1.4.0' ``` 3. Run the following command to install these pods: ```ruby pod install ``` 1. Go to **File** > **Add Packages...** and in **Repository URL**, add `https://github.com/dojo-engineering/dojo-ios-sdk-drop-in-ui`. 2. Enter the latest version number of our SDK. 3. In target of your app, add `dojo-ios-sdk-drop-in-ui`. 4. Click **Add package**. > **Info:** - To get the latest version of the mobile SDK, run `pod update`. > - Ensure that you exclude payment-related fields from tracking if you are using screen recording or session recording services like **LogRocket** or **UXCam**. You can do that by setting `themeSettings.analyticsExcludedFieldsIdentifier` with your identifier value. [![](https://docs.dojo.tech/images/dojo-icons/BookBookmark.svg) **Releases** Details on the latest SDK changes and previous versions.](https://github.com/dojo-engineering/dojo-ios-sdk-drop-in-ui/releases) --- ## Mobile integration {/* -- enable as option 2 import MobileCards from "@site/src/components/MobileCards" */} > Our mobile SDKs are available in iOS, Android, and React Native. Choose your integration. [![iOS](https://img.shields.io/badge/-iOS-blue?logo=Github&labelColor=grey)](https://github.com/dojo-engineering/dojo-ios-sdk-drop-in-ui) [![Android](https://img.shields.io/badge/Android-blue?logo=Github&labelColor=grey)](https://github.com/dojo-engineering/android-dojo-pay-sdk) [![React Native](https://img.shields.io/badge/React_Native-blue?logo=Github&labelColor=grey)](https://github.com/dojo-engineering/react-native-pay-sdk) Our mobile SDKs have been designed with developers in mind, making the integration simple and intuitive to use. Whether you're an experienced developer or just getting started, our SDK provides a smooth checkout experience by allowing you to easily integrate Dojo checkout screens and UI elements in your app. {/* enable as option 2 */} ![](https://docs.dojo.tech/images/mobile-integration.png) {/* ## Supported features // UNCOMMENT WHEN APPROVED */} The Dojo mobile SDKs support the following payment intent features: |Scenario| Currency | Wallet| Card |-------|:--------:|----|-----| |`Created`| **GBP** | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | |`Authorized`| **GBP** | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | |`Canceled`| **GBP** | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | |`Captured`| **GBP** | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | |`Reversed`| **GBP** | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | |`Refunded`| **GBP** | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | ![yes](https://docs.dojo.tech/images/dojo-icons-small/CheckCircle.svg) | [![](https://docs.dojo.tech/images/dojo-icons/AppleLogo.svg) **iOS** Compatible with: iOS 11.0 and later.](/mobile-integration/ios) [![](https://docs.dojo.tech/images/dojo-icons/AndroidLogo.svg) **Android** Compatible with: Android 5.0 and later.](/mobile-integration/android) [![](https://docs.dojo.tech/images/dojo-icons/ReactNative.svg) **React Native** Compatible with: iOS 11.0 and later, Android 5.0 and later.](/mobile-integration/react-native) --- ## Step-by-step guide(4) > Learn how to accept payments in your React Native app using our mobile SDK. This guide explains the process of integrating the checkout experience in your app. ## Checkout experience flow The following explains the flow of a user's journey in the checkout experience. > **Info:** - The term `user` used in this document refers to a customer trying to make a payment through your mobile application. > - This guide assumes you named the button on your checkout screen as **Checkout**. 1. A user visits your app and taps **Checkout**. 2. Your mobile app sends the user's purchase information to your backend. Then, your backend sends this information to Dojo's backend to [create a payment intent](https://docs.dojo.tech/bookings/step-by-step-guide#step-1-create-a-payment-intent). 3. Your mobile app starts the checkout process using the mobile SDK. 4. The mobile SDK collects the user payment details, sends them to the Dojo backend, and presents a result screen to the user. The mobile SDK then notifies the hosting application of the [payment result](https://docs.dojo.tech/bookings/step-by-step-guide#result-code). 5. Your backend receives a [webhook notification](https://docs.dojo.tech/bookings/step-by-step-guide#step-3-handle-post-payment-events) when the payment is completed. ![](https://docs.dojo.tech/images/flow-checkout-page-ios.png) ## How to process a payment This is a step-by-step guide that demonstrates how to process payments with Dojo's backend and your backend into your mobile app using Dojo's mobile SDK. ### Before you start This guide contains the following steps: 1. [Create a payment intent](https://docs.dojo.tech/bookings/step-by-step-guide#step-1-create-a-payment-intent). 2. [Start the checkout process](https://docs.dojo.tech/bookings/step-by-step-guide#step-2-start-checkout-process). 3. [Handle post-payment events](https://docs.dojo.tech/bookings/step-by-step-guide#step-3-handle-post-payment-events). 4. [Test and go live](https://docs.dojo.tech/bookings/step-by-step-guide#step-4-test-and-go-live). ### Step 1. Create a payment intent With the checkout button in your app, call your backend and then call Dojo's backend endpoint to create a payment intent. To create a payment intent, the following parameters are required: - `amount`: This includes the currency and value, in minor units, for example, "1000" for 10.00 GBP. - `reference`: Your unique reference for the payment intent, like the *order number*. Here's an example of how to create a payment intent for 10 GBP on your backend: ```py title="server.py" from urllib import response from flask import Flask, jsonify, request, render_template app = Flask(__name__) @app.route('/checkout', methods=['GET', 'POST']) def hello(): # POST request if request.method == 'POST': print(request.get_json()) # parse as JSON conn = http.client.HTTPSConnection("api.dojo.tech") # call post payment-intent payload = json.dumps({ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order 245" }) headers = { 'Content-Type': "application/json", 'Version': "2024-02-05", 'Authorization': "Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ" # <-- Change to your secret key } conn.request("POST", "/payment-intents/", payload, headers) # handling the response from POST res = conn.getresponse() data = res.read() resp_data = {} resp_data['id'] = json.loads(data)["id"] json_data = json.dumps(resp_data) ``` See the [API reference](https://docs.dojo.tech/api#operation/PaymentIntents_CreatePaymentIntent) for a complete list of parameters that can be used for payment intent creation. For configurations that apply to our mobile SDK, go to [Configurations]. ### Step 2. Start checkout process Once you've created the payment intent, pass the payment intent ID to your payment flow code. > **Info:** To start the checkout process, ensure you have installed the [latest SDK](https://docs.dojo.tech/setup). ```javascript title="capture-card.js" const result = await startPaymentFlow({ intentId: "" }); console.log(result); ``` After the user fills in the payment information on the checkout screen, Dojo processes the payment and redirects the user to the result screen and your app receives a [result code](https://docs.dojo.tech/bookings/step-by-step-guide#result-code). ### Step 3. Handle post-payment events ### Step 4. Test and go live Before going live, test your integration using the test card numbers: ### Result Code After integrating our SDK into your app and making a payment, you will receive a `result` code. Refer to the following result codes for more information. | Result Code | Result |Description | |-----|-----|-----| |`0` |**Successful**|The transaction was successful.| |`3` |**Authorizing**| The card holder hasn't completed 3DS, this status will only be seen on the REST API.| |`4` |**Referred**| The card issuer has parked the transaction awaiting contact with the customer before proceeding to authorize or decline the transaction.| |`5` |**Declined**| The transaction was declined by the card issuer or acquiring bank.| |`20` |**Duplicate Transaction**| The transaction which was processed was a duplicate. Ensure each transaction has a unique OrderId.| |`30` |**Failed**| Error executing transaction.| |`400` |**Invalid Request**| The request has failed validation by our servers and the transaction hasn't been submitted to the gateway. Possible causes for this are invalid transaction type or other data in the request.| |`401` |**Issue with Access Token**| The access token being used isn't valid, the transaction hasn't been submitted to the gateway. This can be caused if the token has already been used or the 30 minute expiry time has elapsed.| |`404` |**No Access Token Supplied**| No access token has been supplied. Transaction hasn't been submitted to the gateway.| |`500` |**Internal Server Error**| There's been an error submitting the transaction, please check the REST API for the status of the transaction.| |`7770` | **Sdk Internal Error**| There's a problem on the SDK side. Contact [Dojo](https://support.dojo.tech/hc/en-gb/requests/new) for more information.| --- --- ## Accept payments with React Native >All you need to know about accepting payments using our React Native SDK. [![](https://docs.dojo.tech/images/dojo-icons/BookBookmark.svg) **Step-by-step Guide** Guide to start accepting payments using React Native SDK.](accept-payments/react-native-step-by-step-guide) [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Need a hand?** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) [![](https://docs.dojo.tech/images/dojo-icons/AppleLogo.svg) **Integrate with Apple Pay** Guide to accept payments with Apple Pay.](../ios/accept-payments/ios-setup-apple-pay) [![](https://docs.dojo.tech/images/dojo-icons/AndroidLogo.svg) **Integrate with Google Pay** Guide to accept payments with Google Pay.](../android/accept-payments/android-setup-google-pay) --- ## React Native integration >Learn more about React Native SDK integration with Dojo. With React Native SDK, you can: - [**Accept payments from all major credit and debit cards**](https://docs.dojo.tech/bookings/react-native/react-native-accept-payments) Allow users to pay using a card that works best for them. - [**Accept Apple Pay payments**](https://docs.dojo.tech/mobile-integration/ios/accept-payments/ios-setup-apple-pay) Integrate Apple Pay to your checkout screen in addition to card payments. - [**Accept Google Pay payments**](https://docs.dojo.tech/mobile-integration/android/accept-payments/android-setup-google-pay) Integrate Google Pay to your checkout screen in addition to card payments. --- ## Ready to get started? [![](https://docs.dojo.tech/images/dojo-icons/Wrench.svg) **Install SDK** Install our React Native SDK to start accepting payments in mobile apps.](react-native/setup) --- ## Setup(React-native) > Learn how to set up the React Native SDK. [![GitHub release](https://img.shields.io/github/v/release/dojo-engineering/react-native-pay-sdk?logo=Github&labelColor)](https://github.com/dojo-engineering/react-native-pay-sdk/releases) This package is published privately to GitHub packages. ## Before you begin Before using our React Native SDK, you must [authenticate `npm` or `yarn` with GitHub](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry#installing-a-package). ## Adding dependencies To add the dependencies to your environment: 1. Add the package to your project. ```ruby npm install https://github.com/dojo-engineering/react-native-pay-sdk/ ``` 2. According to your environment, add the following dependencies to your project: Add the native dependencies to your Podfile: ```ruby title="Podfile" pod 'dojo-ios-sdk-drop-in-ui', :git => 'git@github.com:dojo-engineering/dojo-ios-sdk-drop-in-ui.git', :tag => '1.3.2' pod 'dojo-ios-sdk', :git => 'git@github.com:Dojo-Engineering/dojo-ios-sdk.git', :tag => '1.4.0' ``` Add the native dependencies to your apps build.gradle: ```java title="build.gradle" dependencies { ... implementation ("tech.dojo.pay:sdk:1.6.2") implementation ("tech.dojo.pay:uisdk:1.3.5") } ``` Add the necessary repositories to retrieve the dependencies: ```java title="build.gradle" repositories { ... maven { url = uri("https://cardinalcommerceprod.jfrog.io/artifactory/android") credentials { // Contact Dojo support for credentials username = "" password = "" } } } ``` You must set the credentials for accessing both repositories in your `~/.gradle/gradle.properties`: ```java cardinal.user={cardinal user} cardinal.key={cardinal password} ``` Add the following code to your apps `MainActivity.java`: ```java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); DojoPay.init(this); } ``` > **Info:** Ensure that you exclude payment-related fields from tracking if you are using screen recording or session recording services like **LogRocket** or **UXCam**. You can do that by setting `themeSettings.analyticsExcludedFieldsIdentifier` with your identifier value. [![](https://docs.dojo.tech/images/dojo-icons/BookBookmark.svg) **Releases** Details on the latest SDK changes and previous versions.](https://github.com/dojo-engineering/react-native-pay-sdk/releases) --- ## Strong Customer Authentication [Strong Customer Authentication (SCA)](https://www.fca.org.uk/firms/strong-customer-authentication) is a security protocol that requires customers to provide at least two forms of authentication before completing an online transaction. It is designed to reduce fraud and increase security for online transactions, especially for electronic payment systems that use credit cards, bank transfers, and e-wallets. Under SCA, customers are required to provide two or more of the following forms of authentication: - Something the customer knows (such as a password or PIN) - Something the customer has (such as a mobile phone or a smart card) - Something the customer is (such as a fingerprint or facial recognition) SCA is mandated by the [European Union's Payment Services Directive 2 (PSD2)](https://www.ecb.europa.eu/paym/intro/mip-online/2018/html/1803_revisedpsd.en.html) for all electronic payment transactions initiated by customers in the [European Economic Area (EEA)](https://www.efta.int/eea). It aims at protecting customers' financial data and prevent unauthorized access to their accounts. --- ## Adobe Commerce > Learn how to install and configure **Dojo for Adobe Commerce**. ## Install the module The following instructions apply to [Magento Commerce (Cloud)](https://business.adobe.com/uk/products/magento/magento-commerce.html). * Make sure you're set up with Magento. See the [readme on GitHub](https://github.com/magento/magento2/blob/2.4-develop/README.md) for more information on system prerequisites and pre-start instructions. The Dojo Magento module available on the [Magento Marketplace](https://marketplace.magento.com/dojo-payments-dojo-payments.html) is for **Magento Commerce (Cloud)**. 1. Connect to your Magento environment using SSH. 2. Navigate to the root directory of your Magento store and install Dojo Magento: ```sh composer require dojo_payments/dojo-payments composer update ``` 3. Activate the module: ```sh bin/magento module:enable Dojo_DojoPayments ``` 4. Set up the module in your Magento environment: ```sh php bin/magento setup:upgrade ``` 5. Deploy the static view files: ```sh php bin/magento setup:static-content:deploy ``` 6. Clean the cache: ```sh php bin/magento cache:clean ``` > **Info:** For detailed instructions, see [Install an Extension](https://experienceleague.adobe.com/en/docs/commerce-operations/installation-guide/tutorials/extensions) > > > ## How to configure the module > > 1. Login to the Magento admin panel and go to **Stores** -> **Configuration** -> **Sales** -> **Payment Methods**. > 2. If the Dojo payment method does not appear in the list of the payment methods, go to > **System** -> **Cache Management** and clear the Magento cache by clicking on the **Flush Magento Cache** button. > 3. Go to **Payment Methods** and click the **Configure** button next to the payment method **Dojo** to expand the configuration settings. > 4. Set **Enabled** to **Yes**. > > ### Adding your specific integration details: > 1. [Create an API key](https://docs.dojo.tech/bookings/step-by-step-guide#step-1-create-an-api-key). > 2. [Use your API key](https://docs.dojo.tech/bookings/step-by-step-guide#step-2-use-your-api-key). > 3. [Add your webhook endpoint](https://docs.dojo.tech/bookings/step-by-step-guide#step-3-add-a-webhook-endpoint). > 4. [Use your webhook endpoint](https://docs.dojo.tech/bookings/step-by-step-guide#step-4-use-your-webhook-endpoint). > > ### Step 1: Create an API key > > After installing the module, you need to [create an API key](https://docs.dojo.tech/development-resources/portal#api-keys) from the [developer portal](https://docs.dojo.tech/development-resources/portal). > > **Info:** Ensure that you use the production API key. ### Step 2: Use your API key 1. Copy the API key that you created. 2. In the **Magento** module page, paste your API key in the **Secret API Key** field. 3. Click the **Save config** button. ### Step 3: Add a webhook endpoint > **Info:** Webhooks are crucial as they ensure orders are updated to the correct status in Magento based on the payment intent status communicated by Dojo. > > > 1. In the **Developer portal**, go to **Webhooks** and click the **Add endpoint** button. > 2. Enter the endpoint URL. > **Info:** This is your Magento public URL followed by `/dojo2/checkout/notification`. For example, `https://yourwebsite.com/dojo2/checkout/notification`. 3. Click **Select events** under **Select Dojo events to listen to**. 4. Select **Status update** event. This displays the payment intent status. > **Info:** You must select only **Status update** event. The rest of the events aren't needed. 5. Click the **Add events** button. 6. Click the **Add endpoint** button. ### Step 4: Use your webhook endpoint 1. In the webhooks page of the **Developer portal**, click the key under **Secret value** of your **URL**. This copies the secret value key to your clipboard. 2. In the **Magento** module page, paste your key in the **Webhook Secret** field. 3. Click the **Save config** button. You are now all set to accept payments using Dojo checkout for your ecommerce transactions. Email [devsupport@dojo.tech](mailto:devsupport@dojo.tech) for any issues you encounter during the installation process. --- ## Magento Open Source > Learn how to install and configure **Dojo for Magento Open Source**. ## Install the module The following instructions apply to [Magento Open Source](https://business.adobe.com/products/magento/open-source.html) versions **2.3.x** and **2.4.x** (tested up to [2.4.6](https://experienceleague.adobe.com/docs/commerce-operations/release/notes/magento-open-source/2-4-6.html)). * Make sure you're set up with Magento. See the [readme on GitHub](https://github.com/magento/magento2/blob/2.4-develop/README.md) for more information on system prerequisites and pre-start instructions. ## Download and Install the Plugin 1. **[Download](https://docs.dojo.tech/plugins/dojo-payments-magento-2-0-3.zip) the Dojo plugin ZIP file.** 2. Extract the `.zip` file into the `app/code` directory of your Magento installation: ```bash mkdir -p app/code/Dojo/DojoPayments unzip dojo-payments-magento-2-0-3.zip -d app/code/Dojo/DojoPayments ``` 3. Activate the module: ```sh bin/magento module:enable Dojo_DojoPayments ``` 4. Set up the module in your Magento environment: ```sh php bin/magento setup:upgrade ``` 5. Deploy the static view files: ```sh php bin/magento setup:static-content:deploy ``` 6. Clean the cache: ```sh php bin/magento cache:clean ``` ## How to configure the module 1. Login to the Magento admin panel and go to **Stores** -> **Configuration** -> **Sales** -> **Payment Methods**. 2. If the Dojo payment method does not appear in the list of the payment methods, go to **System** -> **Cache Management** and clear the Magento cache by clicking on the **Flush Magento Cache** button. 3. Go to **Payment Methods** and click the **Configure** button next to the payment method **Dojo** to expand the configuration settings. 4. Set **Enabled** to **Yes**. ### Adding your specific integration details: 1. [Create an API key](https://docs.dojo.tech/bookings/step-by-step-guide#step-1-create-an-api-key). 2. [Use your API key](https://docs.dojo.tech/bookings/step-by-step-guide#step-2-use-your-api-key). 3. [Add your webhook endpoint](https://docs.dojo.tech/bookings/step-by-step-guide#step-3-add-a-webhook-endpoint). 4. [Use your webhook endpoint](https://docs.dojo.tech/bookings/step-by-step-guide#step-4-use-your-webhook-endpoint). ### Step 1: Create an API key After installing the module, you need to [create an API key](https://docs.dojo.tech/development-resources/portal#api-keys) from the [developer portal](https://docs.dojo.tech/development-resources/portal). > **Info:** Ensure that you use the production API key. > > > ### Step 2: Use your API key > > 1. Copy the API key that you created. > 2. In the **Magento** module page, paste your API key in the **Secret API Key** field. > 3. Click the **Save config** button. > > ### Step 3: Add a webhook endpoint > > **Info:** Webhooks are crucial as they ensure orders are updated to the correct status in Magento based on the payment intent status communicated by Dojo. 1. In the **Developer portal**, go to **Webhooks** and click the **Add endpoint** button. 2. Enter the endpoint URL. > **Info:** This is your Magento public URL followed by `/dojo2/checkout/notification`. For example, `https://yourwebsite.com/dojo2/checkout/notification`. > > 3. Click **Select events** under **Select Dojo events to listen to**. > 4. Select **Status update** event. This displays the payment intent status. > **Info:** You must select only **Status update** event. The rest of the events aren't needed. 5. Click the **Add events** button. 6. Click the **Add endpoint** button. ### Step 4: Use your webhook endpoint 1. In the webhooks page of the **Developer portal**, click the key under **Secret value** of your **URL**. This copies the secret value key to your clipboard. 2. In the **Magento** module page, paste your key in the **Webhook Secret** field. 3. Click the **Save config** button. You are now all set to accept payments using Dojo checkout for your ecommerce transactions. Email [devsupport@dojo.tech](mailto:devsupport@dojo.tech) for any issues you encounter during the installation process. --- ## Release notes >Learn more about latest changes, improvements, and bug fixes for **Dojo Magento**. ## Fixed issues ### Version 2.0.3 - Updated the plugin to reflect the latest Dojo brand design. ### Version 2.0.2 - Enhanced logic for processing amounts and values to ensure greater accuracy and reliability ### Version 2.0.1 - Updated extension to ensure full compatibility with Magento 2.4.6 - Introduced additional logging capabilities to improve diagnostics and troubleshooting - Apple Pay and Google Pay now supported on Magento Open Source ### Version 2.0.0 - Initial release to Adobe Marketplace :::warning Legacy version 1.0.x If you are using an older version of the plugin, Dojo recommends that you update to the latest version from the Adobe Marketplace. The legacy version has limited features with limited support. If you need help in upgrading to the latest version, reach out to [Dojo support](https://support.dojo.tech/hc/en-gb). --- ## Magento The Dojo Magento module allows for Magento e-commerce transactions to be processed using Dojo's secure [checkout page](https://docs.dojo.tech/payments/accept-payments/online-payments/checkout-page) which offers Apple Pay, Google Pay, and handles all security including 3DS2. - **Adobe Commerce**: The Dojo module for Adobe Commerce is available for download from the [Magento Marketplace](https://marketplace.magento.com/dojo-payments-dojo-payments.html). - **Magento Open Source**: The Dojo module for Magento Open Source can be downloaded from the [installation guide](https://docs.dojo.tech/plugins/magento/installation-guide-open-source). > **Info:** Dojo recommends that you install the latest version of the Dojo Magento module if you are still using version 1.0.x. > > > ## See how it works > Watch this video when installing and enabling the Dojo Magento module to ensure it's up and running! > > > > ## Prerequisites > Ensure your [Developer Portal account is setup](https://docs.dojo.tech/development-resources/portal) > > --- > > ## OpenCart > > [OpenCart](https://www.opencart.com/) is a lightweight open-source e-commerce platform geared primarily towards small to medium-sized online businesses. It > has a user-friendly interface and uncomplicated admin panel, along with flexibility through various [extensions](https://www.opencart.com/index.php?route=marketplace/extension). > The Dojo plugin for OpenCart 3 allows you to integrate Dojo payments with an OpenCart online store. It has been tested up to OpenCart version [3.0.3.6](https://github.com/opencart/opencart/releases/tag/3.0.3.6). > > ## Download and install the plugin > > * **[Download](https://www.opencart.com/index.php?route=marketplace/extension/info&extension_id=46379) the Dojo plugin from the OpenCart Marketplace.** > > ## Install using Extension Installer > > OpenCart includes an [Extension Installer](https://docs.opencart.com/en-gb/extension/installer/) which should simplify the next steps in setting up the plugin. > > 1. Login to the **OpenCart Admin Panel** > 2. Go to **Extensions** -> **Extensions Installer** -> Upload to upload the extension's zip file > 3. Go to **Extensions** -> **Extensions** -> **Payments** and click the **Install** button next to **Dojo**. > 4. Click the **Edit** button next to **Dojo** to configure the extension. > 5. Set **Extension Status** to **Enabled**. > 6. Set your **Gateway Username/URL** and **Gateway JWT**. > 7. Set the **Gateway Environment** to **Test** or **Production**. > 8. Optionally, set the rest of the settings as per your needs. > 9. Click the **Save** button. > > ## Manual installation > > If you're unable to use the Extension Installer, or it's not appropriate for your integration, you can manually install the Dojo > for OpenCart plugin: > > 1. Unzip the extension's file and upload the content of the upload folder to the root folder of your OpenCart. > 2. Login to the **OpenCart Admin Panel** > 3. Go to **Extensions** -> **Extensions** -> **Payments** and click the **Install** button next to **Dojo**. > 4. Click the **Edit** button next to **Dojo** to configure the extension > 5. Set **Extension Status** to **Enabled**. > 6. Set your **Gateway Username/URL** and **Gateway JWT** > 7. Set the **Gateway Environment** to **Test** or **Production**. > 8. Optionally, set the rest of the settings as per your needs. > 9. Click the **Save** button. > > ## Changelog > ### Version 1.0.2 > - Updated checkout to fix deprecated function. > > ### Version 1.0.1 > - Added `metaData` parameter for API requests. > - Removed `userAgent` header and `userAgent` parameter for API requests. > > **Note:** The **Dojo for OpenCart** plugin is not currently compatible with Google Pay or Apple Pay. > > Email [devsupport@dojo.tech](mailto:devsupport@dojo.tech) for any issues or problems! > > --- > > ## Plugins > > Plugins are our no-code payments solutions. > > **Tip:** If we don’t support your platform, [let us know](https://support.dojo.tech/hc/en-gb). Setting up a custom Dojo integration is going to require some development know-how, but you can use any number of third-party platforms to make it easier. If you do use a third-party platform to build and maintain your site, you can add Dojo payments to it with a plugin. Try one of our recommended solutions for your site: --- ## PrestaShop [PrestaShop](https://prestashop.com/) is an e-commerce platform with a modular architecture, catering to businesses of different sizes. It offers customization options and scalability, and is supported by an active [community](https://www.prestashop.com/forums/) and [marketplace](https://addons.prestashop.com/en/489-marketplaces). The **Dojo for PrestaShop** plugin integrates Dojo's [checkout page](https://docs.dojo.tech/payments/accept-payments/online-payments/checkout-page) as a [PrestaShop module](https://devdocs.prestashop-project.org/8/modules/). ## Download and install the plugin * **[Download](https://docs.dojo.tech/plugins/dojo-prestashop-1-0-2.zip) the Dojo plugin ZIP file.** ### Requirements * PrestaShop 1.7 (tested up to [1.7.7.4](https://build.prestashop-project.org/news/2021/prestashop-1-7-7-4-maintenance-release/)) * [PHP 7.0](https://www.php.net/releases/7_0_0.php) or higher (a version with security support is highly recommended) * [PHP CURL extension](https://www.php.net/manual/en/curl.installation.php) * [PHP JSON extension](https://www.php.net/manual/en/json.installation.php) * [PCI](https://www.pcisecuritystandards.org/)-certified server using [TLS 1.2+](https://www.ncsc.gov.uk/guidance/using-tls-to-protect-data). ### Installation 1. Login into the admin area of your PrestaShop website. 2. Go to **Modules** -> **Module Manager**. 3. Click the **Upload a module** button at the top of the page. 4. A pop-up window will appear for uploading the module. 5. Click the **Select file** link and choose the module's ZIP file, or drop the module's ZIP file into the designated area. 6. The module will be installed automatically and a message about the successful installation should appear. 7. Click the **Configure** button to configure the module. Skip to step 4. of the Configuration section below to keep on configuring from here. ## Configuration 1. Login into the admin area of your PrestaShop website. 2. Go to **Modules** -> **Module Manager**. 3. Find the **Dojo** module and click the **Configure** button. 4. Set your **Gateway Username/URL** and **Gateway JWT**. 5. Set the **Gateway Environment** to **Test** or **Production** based on whether you want to use the Test or the Production gateway environment. 6. Optionally, set the rest of the settings as per your needs. 7. Click the **Save** button at the bottom of the page. 8. Go to **Advanced Parameters** -> **Performance** and click the **Clear cache** button. ## Enabling secure checkout 1. Make sure TLS is configured on your PCI-DSS certified server. 2. Login into the admin area of your PrestaShop website. 3. Go to **Shop Parameters** -> **General**. 4. Click the **Please click here to check if your shop supports HTTPS** link. 5. Set **Enable SSL** to **YES**. 6. Click the **Save** button at the bottom of the page. 7. Set **Enable SSL on all pages** to **YES**. 8. Click the **Save** button again. ## Changelog ### Version 1.0.2 - Updated checkout to fix deprecated function. ### Version 1.0.1 - Added `metaData` parameter for API requests. - Removed `userAgent` header and `userAgent` parameter for API requests. **Note:** The **Dojo for PrestaShop** plugin is not currently compatible with Google Pay or Apple Pay. Email [devsupport@dojo.tech](mailto:devsupport@dojo.tech) for any issues or problems! --- ## Configure > Learn how to configure and enable the **Dojo for WooCommerce** plugin. After you have enabled the **Dojo checkout** method, do the following to begin setting up the plugin in your WooCommerce ecosystem: 1. In the **WooCommerce** plugin, go to **Settings** > **Payments**. 2. Under **Payment Methods**, click **Finish set up** in the **Dojo checkout** method. ![Configure](https://docs.dojo.tech/images/dojo-for-woocommerce-setup-wp.png) This takes you to **Dojo checkout** settings where you can configure the plugin. ## How to configure the plugin To configure the **Dojo for WooCommerce** plugin, do the following: 1. [Create an API key](https://docs.dojo.tech/explore/changelog#step-1-create-an-api-key). 2. [Use your API key](https://docs.dojo.tech/explore/changelog#step-2-use-your-api-key). 3. [Add your webhook endpoint](https://docs.dojo.tech/explore/changelog#step-3-add-a-webhook-endpoint). 4. [Use your webhook endpoint](https://docs.dojo.tech/explore/changelog#step-4-use-your-webhook-endpoint). ### Step 1: Create an API key After installing the plugin, you need to [create an API key](https://docs.dojo.tech/development-resources/portal#api-keys) from the [developer portal](https://docs.dojo.tech/development-resources/portal). ### Step 2: Use your API key 1. Copy the API key that you created. 2. In the **WooCommerce** plugin page, go to **Settings** > **Payments**. 3. In the **Dojo checkout** method, click **Manage**. This takes you to the **Payments** > **Dojo checkout** page. 4. Under **Gateway settings**, in the **Secret API key** field, paste the API key. 5. Click the **Save changes** button. > **Info:** note > Ensure that you use the production API key. ### Step 3: Add a webhook endpoint 1. In the **Developer portal**, go to **Webhooks** and click the **Add endpoint** button. 2. Enter the endpoint URL. > **Info:** note > This is your WordPress public URL followed by `/?wc-api=wc_dojo`. For example, `https://yoursite.com/?wc-api=wc_dojo`. 3. Click **Select events** under **Select Dojo events to listen to**. 4. Select **Status update** event. This displays the payment intent status. > **Info:** note > You must select only **Status update** event. The rest of the events aren't needed. 5. Click the **Add events** button. 6. Click the **Add endpoint** button. ![Webhook endpoint](https://docs.dojo.tech/images/dojo-for-woocommerce-webhook-endpoint.png) ### Step 4: Use your webhook endpoint 1. In the webhooks page of the **Developer portal**, click the key under **Secret value** of your **URL**. This copies the secret value key to your clipboard. 2. In the **WooCommerce** plugin page, go to **Settings** > **Payments** > **Dojo checkout**. 3. Under **Webhook settings**, in the **Webhook secret** field, paste the key you copied. ![Webhook secret](https://docs.dojo.tech/images/dojo-for-woocommerce-webhook-key-wp.png) 4. Click the **Save changes** button. You are now all set to accept payments using Dojo checkout for your ecommerce transactions. --- ## Enable Dojo checkout >Learn how to enable Dojo checkout in the WooCommerce plugin settings. After you have installed and activated the **Dojo for WooCommerce** plugin, enable the **Dojo checkout** method in the WooCommerce plugin settings. This enables you to accept payments from credit or debit cards using Dojo. To enable the **Dojo checkout** method, do the following: 1. Login to your WordPress site, and go to **WooCommerce** > **Settings** > **Payments**. 2. Under **Payment Methods**, enable **Dojo checkout**. ![Enable](https://docs.dojo.tech/images/dojo-for-woocommerce-enable-wp.png) 3. Click **Save changes** button. --- ## Install and activate > Learn how to install and activate the Dojo for WooCommerce plugin. The Dojo plugin is available for [WooCommerce](https://woo.com/) and integrated with the Dojo [Online Checkout](https://docs.dojo.tech/payments/accept-payments/online-payments/checkout-page) page. It uses Dojo’s secure payment form to take payment, then redirects a customer back to your site for order confirmation. > **Info:** Dojo recommends that you install the [latest version](https://wordpress.org/plugins/dojo-for-woocommerce/) of Dojo for WooCommerce > plugin if you are still using version 1.0.x. ## Prerequisites 1. Go to **WooCommerce** -> **Settings** -> **Payment**. 2. Click the **Manage** button for the **Dojo Checkout** payment method. 3. Check the **Enable Dojo Checkout** checkbox. 4. Enter your **Secret API key**. 5. Enter your **Webhook secret**. 6. Optionally, set the rest of the settings as per your needs. 7. Click the **Save changes** button. # Installation To install and activate the plugin, do the following: 1. Login to your WordPress site. 2. Go to the **Plugins** > **Add New**. 3. In the search bar, type **Dojo for WooCommerce** and press enter. 4. Click the **Install Now** button next to the **Dojo for WooCommerce** plugin. ![Install Now](https://docs.dojo.tech/images/dojo-for-woocommerce-install-wp.png) 5. After you install the plugin, click the **Activate** button. ![Activate](https://docs.dojo.tech/images/dojo-for-woocommerce-activate-wp.png) --- ## Introduction >Learn about the Dojo for WooCommerce plugin The [**Dojo for WooCommerce**](https://wordpress.org/plugins/dojo-for-woocommerce/) plugin is a free plug-in that includes all Dojo's key payment functionality, ready to integrate with [WooCommerce](https://woo.com/). This means that with the Dojo for WooCommerce plugin, customers can pay using a [Dojo checkout page](https://docs.dojo.tech/payments/accept-payments/online-payments/checkout-page) that is integrated seamlessly into a WooCommerce online storefront. **WooCommerce** is a WordPress e-commerce plugin, so it uses core functionality that will already be familiar to WordPress site developers. That includes many of the same [hooks](https://woocommerce.github.io/code-reference/hooks/hooks.html) and [filters](https://woo.com/document/woocommerce-product-search/api/filters/?quid=fcb2f0458711b6247f18721be34a00b4). Because of its open-source community there are a range of free-to-use themes available online, and WooCommerce also includes both [built-in shortcodes](https://woo.com/document/woocommerce-shortcodes/) and [widgets](https://wordpress.org/documentation/article/block-based-widgets-editor/), which can give a quick view on a variety of useful information, including sales and reviews, stock levels, and store performance. ## See how it works Watch this video when installing and enabling the Dojo for WooCommerce plugin to ensure it's up and running! Email [devsupport@dojo.tech](mailto:devsupport@dojo.tech) for any issues or problems! --- ## Release notes(Woocommerce) >Learn more about the latest changes, improvements, and bug fixes in the **Dojo for WooCommerce** plugin. Dojo for WooCommerce plugin is available on WordPress. Dojo recommends that you [install the latest version](https://wordpress.org/plugins/dojo-for-woocommerce/) of the plugin from the WordPress plugin directory. ### Version 2.1.0 - **Enhancement**: Added WooCommerce Blocks compatibility - Tested and updated compatibility with the latest versions of WooCommerce, WordPress and PHP ### Version 2.0.15 - **Enhancement**: Added support for Italian and Spanish translations. - Fixed an issue affecting pickup products and order notes. ### Version 2.0.14 - Updated compatibility with the latest versions of WooCommerce and WordPress. - Updated API versioning integration for better performance and stability. ### Version 2.0.13 - Updated error logging and added the collection of email addresses and phone numbers for 3DS2 authentication. ### Version 2.0.12 - Updated the plugin to reflect the latest Dojo brand design. ### Version 2.0.11 - Upgraded plugin to use the latest Dojo API version. ### Version 2.0.10 - Addressed an issue with how the plugin determined compatibility with websites' SSL/TLS certificates. ### Version 2.0.9 - **New Feature**: Introduced an option to exclude item lines from the hosted checkout page, providing a cleaner and more customizable checkout experience. - **Enhancement**: Added plugin observability, allowing for better monitoring and troubleshooting capabilities. ### Version 2.0.8 - **Enhancement**: Added support for High Performance Order Storage [HPOS](https://woo.com/document/high-performance-order-storage/). ### Version 2.0.7 - Fixed an issue affecting orders with virtual products where shipping information was not collected in the order details. - **Enhancement**: Added a 60-minute timeout for payment intents to enhance security and consistency. ### Version 2.0.6 - Updated broken links. - Extended the character limit for `Product Name`. - Fixed PHP 8 compatibility issue. ### Version 2.0.5 - Tax, shipping, and total amount information have been added to the checkout page. ### Version 2.0.4 - An intermittent total rounding issue affecting the online checkout page and the refund flow has been fixed. - A PHP 7.2 compatibility issue has been fixed. ### Version 2.0.3 - Installation issue with running on PHP version before 7.4. ### Version 2.0.2 - Bug fixes and security enhancements. ### Version 2.0.1 - Initial release. :::warning Legacy version 1.0.x If you are using an older version of the plugin, Dojo recommends that you update to the latest version from the WordPress plugin directory. The legacy version has limited features with limited support. If you need help in upgrading to the latest version, reach out to [Dojo support](https://support.dojo.tech/hc/en-gb). --- ## Dojo for WooCommerce >Learn how to download, install, and configure the Dojo for WooCommerce plugin. Also see the latest changes to the plugin in our release notes. [![](https://docs.dojo.tech/images/dojo-icons/Presentation.svg) **Introduction** Know more about Dojo for WooCommerce plugin.](/plugins/woocommerce/introduction) [![](https://docs.dojo.tech/images/dojo-icons/PenNib.svg) **Release notes** Stay updated with new features, issues resolved, known issues, or improvements to the plugin.](/plugins/woocommerce/release-notes) [![](https://docs.dojo.tech/images/dojo-icons/Settings.svg) **Install** Find out how to install the plugin.](/plugins/woocommerce/install-and-activate) [![](https://docs.dojo.tech/images/dojo-icons/Toggle-1.svg) **Enable Dojo checkout** Find out how to enable Dojo checkout after you activate the plugin.](/plugins/woocommerce/enable-dojo-checkout) [![](https://docs.dojo.tech/images/dojo-icons/Wrench.svg) **Configure** Find out how to configure the plugin and setup a payment.](/plugins/woocommerce/configure) [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Need a hand?** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) --- ## API keys >Learn how to manage your API keys. The Dojo API uses [Basic HTTP authentication](https://datatracker.ietf.org/doc/html/rfc7617). To authenticate requests you'll need to provide your API key. Use the [Developer Portal](https://docs.dojo.tech/explore/portal/#api-keys) to create a key or manage an existing key. ## Key format Keys are structured in a way that has semantic meaning: * They start with the prefix `sk_` (standing for security key). * After that, they contain the environment prefix, which is either: `sandbox_` or `prod_`. * Finally, the key content comes after that. Here is an example test key: `sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ`. ## How to use API keys You must include your secret API key in the authorization header of all requests, for example: ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' \ --data '{ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order-0001", "paymentMethods": [ "Card", "Wallet" ] }' ``` API requests without authentication will fail. ## Create a new key You can use a new API key as soon as you generate it. An API key is location bound. If your company account has different [location accounts](https://docs.dojo.tech/explore/portal#account-structure), make sure you have selected the correct one before generating the key. ## Delete a key You may delete API keys at any time. A deleted key stops working immediately. Key deletion **cannot** be undone. To delete a key, click the three dots next to your secret key and choose **Delete key**. --- ## Learn more [![](https://docs.dojo.tech/images/dojo-icons/Planet.svg) **Developer Portal** Find out more about Dojo Developer Portal and how to use it.](portal) --- ## Best Practices Protecting your website from fraudulent activity like card slamming is essential for maintaining the security of your customers' data and ensuring compliance with payment regulations. This guide outlines common threats and actionable steps you can take to reduce risk. ## Preventing Card Slamming and Automated Abuse Card slamming, a form of card testing, involves attackers using scripts to rapidly submit stolen card details to a checkout form. These attacks often aim to find valid card numbers by testing hundreds or thousands in quick succession. Here are some measures to help block these attacks: ### Add CAPTCHA or Bot Detection To reduce the risk of automated abuse: - Add CAPTCHA to any page that triggers payment or card checks. - Enforce checks both client-side and server-side. - Combine CAPTCHA with rate-limiting (e.g. block after five failures per IP). - Monitor IPs and block suspicious sources. - Consider tools like reCAPTCHA (v2, v3, or Enterprise) for scoring-based risk analysis. - Adjust thresholds or switch to visible CAPTCHA if abuse continues. CAPTCHA is best used as a short-term barrier. It may affect conversions slightly, so consider removing it when no longer needed. ### Additional Tips - **Rate limit requests**: Throttle repeated attempts from the same IP address or device fingerprint. - **Review analytics and logs**: Monitor for unusual patterns or spikes in failed attempts to identify abuse early. --- ### Contact information For technical questions on integration, design or securing your setup, feel free to contact our support team or consult the API reference for further configuration options. --- ## Branding ## Brand guidelines Make sure our brand is always powerful and consistent with the right logos, colours, and other brand assets. Get the full guidelines and assets in the links below. - **Dojo brand guidelines – get to the good stuff** Our brand idea, get to the good stuff, sits at the heart of everything we do. It’s the spirit and attitude of Dojo. Find out how to capture it visually and verbally – [download the brand guidelines here](https://docs.dojo.tech/static//branding/merchant-logo-usage-guidelines.pdf). - [Download Dojo Logo Black (SVG)](https://docs.dojo.tech/static/branding/DOJO_LOGO_DOJO_BLACK_RGB.svg) - [Download Dojo Logo White (SVG)](https://docs.dojo.tech/static/branding/DOJO_LOGO_DOJO_WHITE_RGB.svg) - [Download Dojo Logo Black (PNG)](https://docs.dojo.tech/static/branding/DOJO_LOGO_DOJO_BLACK_RGB.png) - [Download Dojo Logo White (PNG)](https://docs.dojo.tech/static/branding/DOJO_LOGO_DOJO_WHITE_RGB.png) ### Guidelines for external brands Every brand has specific rules for logo usage, such as size, colour, and placement. Read the guidelines to make sure you stick to the branding of Visa, Mastercard, and American Express. - **Visa** Download Visa's branding guidelines and logos from [Visa Merchant Signage](https://www.merchantsignage.visa.com/brand_guidelines). - **Mastercard** Access Mastercard's branding materials through the [Mastercard Brand Center](https://www.mastercard.com/brandcenter/en/download-artwork). - **American Express** Download American Express logos and branding resources from [American Express Merchant Supplies](https://www.americanexpress.com/en-gb/business/merchant/supplies/details/?pid=WEBLOGO1). ### Contact information Questions on Dojo branding or designing with external partners? Contact marketing@dojo.tech and the brand team will swoop in and help. For technical questions on integration or design, feel free to contact our support team. --- ## Code samples > Working code samples to plug-and-play. Our code samples are up and ready to integrate with your web apps and mobile apps. We have a dedicated GitHub repository to help you: - Create your own Checkout page or use our [prebuilt](https://docs.dojo.tech/payments/accept-payments/online-payments/checkout-page) one. - Configure and use [Dojo components](https://docs.dojo.tech/payments/accept-payments/online-payments/components). - Build a checkout experience on [mobile devices](https://docs.dojo.tech/mobile-integration) and web environments. Choose from the following list of integrations to get started: --- ## Data types Dojo uses a coherent format for data such as currencies, amounts, and dates across all of our APIs. ## Currency and amount We use the [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) standard for defining currencies. For examples, USD for US dollars or GBP for Great British pounds. We express amounts in minor units. That means they're expressed in the smallest unit of currency. For example, a GBP value of 500 represents £5, and a GBP value of 50 represents £0.50 (fifty pence). ``` json { "value": 500, "currencyCode": "GBP" } ``` ## Date and time Dojo APIs express date and time according to the [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format standard with combined date, time and timezone expressed in UTC. For example, `2021-05-12T07:45:00Z` represents the 12th of May 2021 at 07:45:00. The exception to this is the `expiryDate` field, which accepts values in the MM/YY format. ``` json { "transactionDateTime": "2021-05-12T07:45:00Z", "expiryDate": "04/21" } ``` ## Country Dojo APIs describe country codes using the two-letter [ISO 3166–1–alpha–2](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes) standard. For example, GB for Great Britain. ``` json { "countryCode": "GB" } ``` --- ## Development resources >This section contains resources to help developers build integrations with the Dojo Payments API. [![](https://docs.dojo.tech/images/dojo-icons/Planet.svg) **Developer Portal** Find out more about Dojo Developer Portal and how you can use it.](/development-resources/portal) [![](https://docs.dojo.tech/images/dojo-icons/TerminalWindow.svg) **API reference** Learn about API and integrate with API endpoints.](/api) [![](https://docs.dojo.tech/images/dojo-icons/Key.svg) **API keys** Learn how to manage your API keys.](/development-resources/api-keys) [![](https://docs.dojo.tech/images/dojo-icons/AnchorSimple.svg) **Webhooks** Subscribe to events and get notifications.](/development-resources/webhooks) [![](https://docs.dojo.tech/images/dojo-icons/Cube.svg) **SDKs** Check our software development kits.](/development-resources/sdk) [![](https://docs.dojo.tech/images/dojo-icons/Paste.svg) **Test cards** Use the card details to test your integrations.](/development-resources/testing) [![](https://docs.dojo.tech/images/dojo-icons/Copy.svg) **Code samples** Clone sample integrations.](/development-resources/code-samples) [![](https://docs.dojo.tech/images/dojo-icons/Message.svg) **Stack Overflow** Find answers to practical questions.](https://stackoverflow.com/questions/tagged/dojo.tech) [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Need a hand?** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) [![](https://docs.dojo.tech/images/dojo-icons/Email.svg) **Email Support** Contact our Partner Enablement team directly.](mailto:partnertech@dojo.tech) --- ## Legacy API keys >Still using Connect-E? Learn how to retrieve the JSON Web Token. > **Info:** Dojo highly recommends that you use the latest [Dojo API keys](https://docs.dojo.tech/explore/api-keys). Going forward, [JWT](https://jwt.io/introduction) tokens will become obsolete with limited support. > If you are using the old APIs to integrate Dojo as a payment method and want to retrieve the JWT token, do the following: 1. In the developer portal, click **Dojo app** and login. 2. In the sidebar, go to **Accounts** > **Locations**. 3. Select the location linked to your website. A **Location details** tab appears. 4. In the **Location details** tab, go to **REMOTE PAYMENTS** > **Developer resources**. Here you can find the JWT token and gateway username. ![JWT token](https://docs.dojo.tech/images/jwt-token.png) --- ## LLM-friendly docs > Use our LLM-friendly documentation to help AI coding assistants integrate with Dojo APIs. If you're using an AI coding assistant like **GitHub Copilot**, **Claude Code**, **Codex**, or similar tools, you can point them to our LLM-optimized documentation for faster, more accurate integration help. ## Available files | File | URL | Description | |------|-----|-------------| | **llms.txt** | [/llms.txt](https://docs.dojo.tech/llms.txt) | Index of all documentation with links — start here | | **llms-full.txt** | [/llms-full.txt](https://docs.dojo.tech/llms-full.txt) | All documentation in a single file | ### By integration type | File | URL | Description | |------|-----|-------------| | **llms-online.txt** | [/llms-online.txt](https://docs.dojo.tech/llms-online.txt) | Online payments — checkout, Components, payment links, and virtual terminal | | **llms-payment-intents.txt** | [/llms-payment-intents.txt](https://docs.dojo.tech/llms-payment-intents.txt) | Payment intents, setup intents, captures, refunds, cancellations, and webhooks | | **llms-inperson-pac.txt** | [/llms-inperson-pac.txt](https://docs.dojo.tech/llms-inperson-pac.txt) | Pay at Counter terminal sessions, captures, refunds, and pre-authorisation | | **llms-inperson-pat.txt** | [/llms-inperson-pat.txt](https://docs.dojo.tech/llms-inperson-pat.txt) | Pay at Table — searching payable orders, locking/unlocking, recording payments, and printable bills | | **llms-epos.txt** | [/llms-epos.txt](https://docs.dojo.tech/llms-epos.txt) | EPOS capability registration, event contracts, and EPOS Data API integration | | **llms-core-concepts.txt** | [/llms-core-concepts.txt](https://docs.dojo.tech/llms-core-concepts.txt) | Shared orders, parties, reservations, tables, areas, terminal sessions, and event vocabulary | | **llms-order-and-pay.txt** | [/llms-order-and-pay.txt](https://docs.dojo.tech/llms-order-and-pay.txt) | Self-service ordering and payment flows coordinated with POS capabilities | | **llms-plugins.txt** | [/llms-plugins.txt](https://docs.dojo.tech/llms-plugins.txt) | WooCommerce, Magento, OpenCart, and PrestaShop plugin setup and troubleshooting | | **llms-bookings.txt** | [/llms-bookings.txt](https://docs.dojo.tech/llms-bookings.txt) | Dojo Bookings / RMS reservations, parties, tables, and POS synchronization | | **llms-mobile-ios.txt** | [/llms-mobile-ios.txt](https://docs.dojo.tech/llms-mobile-ios.txt) | iOS SDK | | **llms-mobile-android.txt** | [/llms-mobile-android.txt](https://docs.dojo.tech/llms-mobile-android.txt) | Android SDK | | **llms-mobile-reactnative.txt** | [/llms-mobile-reactnative.txt](https://docs.dojo.tech/llms-mobile-reactnative.txt) | React Native SDK | | **llms-mobile-ttpoi.txt** | [/llms-mobile-ttpoi.txt](https://docs.dojo.tech/llms-mobile-ttpoi.txt) | Tap to Pay on iPhone | ### OpenAPI specifications For precise API integration, agents can fetch the machine-readable OpenAPI specs directly: - **Dojo API (latest)**: [/api/v3/bundled.json](https://docs.dojo.tech/api/v3/bundled.json) - **Transactions API**: [/transactions/bundled.json](https://docs.dojo.tech/transactions/bundled.json) - **EPOS Data API (REST)**: [/epos-data/bundled.json](https://docs.dojo.tech/epos-data/bundled.json) - **EPOS Data API (WebSocket)**: [/epos-data-asyncapi/bundled.yaml](https://docs.dojo.tech/epos-data-asyncapi/bundled.yaml) - **PCI API**: [/pci-api/bundled.json](https://docs.dojo.tech/pci-api/bundled.json) ## How to use ### GitHub Copilot (Copilot Chat / Copilot Coding Agent) Copy the relevant file URL from the tables above into a prompt like: ``` Fetch the llms-full.txt URL above and use it to help me integrate Dojo payments into my app. ``` ### Claude Code Use the `/fetch` command or point Claude to the file you need: ``` Fetch the llms-payment-intents.txt URL above and help me create a payment intent using the Dojo API. ``` ### OpenAI Codex / ChatGPT Paste the relevant file URL or its content into your prompt: ``` Using the llms.txt URL above, help me set up webhooks for payment notifications. ``` > **Tip:** For focused tasks, prefer the narrowest product-specific file, such as `llms-online.txt`, `llms-payment-intents.txt`, `llms-epos.txt`, `llms-plugins.txt`, or the relevant mobile SDK file, instead of the full documentation. ## What's included These files follow the [llmstxt.org](https://llmstxt.org/) standard and are automatically generated from our documentation. They include: - All human-written guides and tutorials - Links to OpenAPI specifications for all Dojo APIs - Authentication details and API base URLs - Code examples and step-by-step integration guides The files are regenerated with every documentation update, so they're always in sync with the latest docs. --- ## Developer Portal > Find out more about the Dojo Developer Portal and how you can use it. The Developer Portal contains a set of tools that developers can use to manage their integrations with our Dojo APIs, including API keys and WebHooks. **[Login to Dojo Developer Portal](https://developer.dojo.tech/login)** To get started using the Dojo Developer Portal, you'll first need a Dojo account. If you don't have an account, [sign up now](https://account.dojo.tech/register?redirectLink=https:%2F%2Faccount.dojo.tech%2Flogin). ## Sandbox and production environments You can choose between two environments on the Developer Portal: * **Test mode** — This is a sandbox environment that allows you to safely test integrations before using them in production. In this mode, you don’t modify your live data. Use test mode to develop your integration. * **Live mode** — This is the production environment that gives you access to the real data. Use this mode when you’re ready to launch your integration. To switch between the two modes, use the toggle in the left menu. ![](https://docs.dojo.tech/images/test-mode.png) ## Account structure With Dojo, you have a single company account, and one or more sub-accounts called **location accounts**. * Company account — This represents your business entity with us, and holds all your location accounts. * Location accounts — This represent your unique point of sale, like a shop or café. Each location account has two keys: a secret key for the [sandbox environment](https://docs.dojo.tech/explore/changelog#sandbox-and-production-environments) and a secret key for the [production environment](https://docs.dojo.tech/explore/changelog#sandbox-and-production-environments). You can find your keys in the Developer Portal. Learn how to [manage your API keys](https://docs.dojo.tech/explore/api-keys). To view data related to a specific location account, select the drop-down menu in the top left and choose a location account. ![](https://docs.dojo.tech/images/account-menu.png) ## API keys You can create or manage [API keys](https://docs.dojo.tech/explore/api-keys) in the Developer Portal. If your company account has different [location accounts](https://docs.dojo.tech/explore/portal#account-structure), make sure you have selected the correct one before creating the key. When you first log in to the Developer Portal, you'll notice an API key already created, named **Initial API Key**. This key is provided for your convenience, so you don't need to generate one manually. It has access to the **Dojo API**, but is only enabled for the products your account is approved for. You can perform any API request related to those products, just like any key you generate yourself. If you want to use **Online Checkout**, go to the Developer Portal, select **Account activation** from the sidebar, and follow the instructions on the page. More information [here](https://support.dojo.tech/hc/en-gb/articles/5861747539996-The-Developer-Portal). ## WebHooks You can manage WebHooks in the Developer Portal, using the following instructions. You also can manage WebHooks directly, using our [API](https://docs.dojo.tech/explore/webhooks). ### Create a new webhook 1. Go to **Developer Portal** > **Webhooks** and select **+Add endpoint**. 2. Enter your endpoint URL and select the events you want to subscribe to. 3. Click **Add endpoint**. ### Edit, or delete an existing webhook To edit or delete a WebHook, click the three dots next it and select the relevant option. --- ## Learn more [![](https://docs.dojo.tech/images/dojo-icons/AnchorSimple.svg)**Set up notification webhooks** Use WebHooks to receive updates related to your payments.](webhooks) [![](https://docs.dojo.tech/images/dojo-icons/Key.svg)**Generate API keys** Learn how to manage your API keys.](api-keys) --- ## Android > Learn how to use the Dojo Android SDK. ## Pre-requisites - Android version - Generating developer token ## Installing Dojo SDK in the project (from github) ## Configuring Dojo sdk ## Making an API call to Dojo API / Using the Dojo API --- ## .NET > Learn how to work with Dojo's .NET SDK for the Payments API. [![NuGet](https://img.shields.io/nuget/v/dojo.net.svg)](https://www.nuget.org/packages/Dojo.net/) The [Dojo.Net](https://github.com/dojo-engineering/Dojo.Net) [NuGet](https://www.nuget.org/) package is the official Dojo .NET library, supporting [.NET Standard 2.0+](https://learn.microsoft.com/en-us/dotnet/core/introduction), .NET Core 2.0+, and [.NET Framework 4.6.1+](https://dotnet.microsoft.com/en-us/learn/dotnet/what-is-dotnet-framework). ## Installing the SDK The fastest way to start using the package is to install it using the [.NET CLI](https://learn.microsoft.com/en-us/dotnet/core/tools/) [`dotnet add package`](https://learn.microsoft.com/en-us/nuget/consume-packages/install-use-packages-dotnet-cli#install-or-update-a-package) command in your project directory, but you can also use other methods like the NuGet CLI and the Microsoft Package Manager Console. Using the [.NET Core command-line interface (CLI) tools](https://docs.microsoft.com/en-us/dotnet/core/tools/): ```sh dotnet add package Dojo.Net ``` Using the [NuGet Command Line Interface (CLI)](https://docs.microsoft.com/en-us/nuget/tools/nuget-exe-cli-reference): ```sh nuget install Dojo.Net ``` Using the [Package Manager Console](https://docs.microsoft.com/en-us/nuget/tools/package-manager-console): ```powershell Install-Package Dojo.Net ``` From within Visual Studio: 1. Open the Solution Explorer. 2. Right-click on a project within your solution. 3. Click on *Manage NuGet Packages...* 4. Click on the *Browse* tab and search for "Dojo.Net". 5. Click on the Dojo.Net package, select the appropriate version in the right-tab and click *Install*. ## Building In order to build the source code for this SDK, [.NET 3.0+](https://dotnet.microsoft.com/en-us/download/dotnet/3.0) is required: 1. Go to the `src` subfolder. 2. Run: ```sh dotnet build ``` ## Usage Create a `PaymentIntentsClient` instance in your .NET application. Initialize this client with an [`HttpClient`](https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=net-7.0) for managing HTTP requests and an `ApiKeyClientAuthorization` to ensure secure API authentication. Then, you can start handling [payment intents](https://docs.dojo.tech/payments/manage-payments/payment-intent). ```c# Dojo.Net.PaymentIntentsClient client = new PaymentIntentsClient( new HttpClient(), new ApiKeyClientAuthorization(apiKey)); ``` ### Use it as .NET service To use the Dojo.Net SDK as a .NET service, you need to register it in your .NET project. This will configure the SDK to be accessible throughout the application. This code sets up client authorization with your API key and adds an [`HttpClient`](https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=net-7.0) for `IPaymentIntentsClient`. ```c# builder.Services.AddSingleton(new ApiKeyClientAuthorization(apiKey)); builder.Services.AddHttpClient(); ``` ### Automatic retries The library does not automatically retries requests on intermittent failures like connection errors. We suggest you use the [Polly](https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/implement-http-call-retries-exponential-backoff-polly) library to set up a retry policy. This code configures a retry mechanism, allowing the application to automatically retry a failing HTTP request up to three times with increasing delays between retries: ```c# builder.Services .AddHttpClient() .AddTransientHttpErrorPolicy( x => x.WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(3, retryAttempt)))); ``` For any requests, bug or comments, please [open an issue](https://github.com/dojo-engineering/Dojo.Net/pulls) or [submit a pull request](https://github.com/dojo-engineering/Dojo.Net/pulls). --- ## Other SDKs > Learn how to generate your own SDK. You can generate your own SDK for any programming language from our [Open API specification](https://github.com/dojo-engineering/dojo-samples/blob/main/bundled.json) by [OpenAPI Generator](https://openapi-generator.tech/) or [Swagger Codegen](https://swagger.io/tools/swagger-codegen/). --- ## PHP > Learn how to work with Dojo's PHP SDK for the Dojo Payments API. [![Packagist](https://img.shields.io/packagist/v/dojo-engineering/dojo-php.svg)](https://packagist.org/packages/dojo-engineering/dojo-php) The [Dojo.PHP](https://github.com/dojo-engineering/Dojo.Php) is the official Dojo PHP library, supporting the [Dojo API](https://docs.dojo.tech/api). To start using the Dojo PHP SDK: * Get the [SDK package](https://packagist.org/packages/dojo-engineering/dojo-php) from Packagist. * Install the package using [Composer](https://getcomposer.org/) ## Installing the SDK To install the Dojo PHP library, you'll need [Composer](https://getcomposer.org/). If you don't have it installed, make sure to set it up first. Here's how to install the Dojo PHP SDK: 1. Get the SDK package from [Packagist](https://packagist.org/packages/dojo-engineering/dojo-php). 2. Install the package using Composer with the following command: ```sh composer require dojo/dojo-php ``` ## Building the source code To build the Dojo PHP SDK, ensure you have [PHP](https://www.php.net/) [7.4](https://www.php.net/releases/7_4_0.php) or higher installed. Alternatively, use the VSCode [`devcontainer`](https://code.visualstudio.com/docs/devcontainers/containers) for a more streamlined development experience. Do the following: 1. Run: ```sh composer install ``` 2. From the root of the repository, execute the script: ```sh /build/generate-openapi.sh ``` 3. Copy all files from `/generated/src` into `/src` ## Using the PHP SDK to create a payment intent Create a client for the payment intent, using your [API key](https://docs.dojo.tech/explore/api-keys): ```php use Dojo_PHP\ApiFactory; $apiKey = "YOUR_API_KEY"; $client = ApiFactory::createPaymentIntentApi($apiKey); ``` In this step, you create a new payment intent request object. This request object will hold the details of the payment intent that you want to create. ```php $req = new CreatePaymentIntentRequest(); ``` Set a reference for the payment intent (e.g., an order number or unique identifier): ```php $req->setReference("test"); ``` Create a [`Money`](https://docs.dojo.tech/api/#tag/Payment-intents/operation/PaymentIntents_CreatePaymentIntent) object to specify the amount and currency ```php $money = new Money(); ``` Set the amount to 100 in the specified currency, in [minor units](https://docs.dojo.tech/explore/data-types#currency-and-amount). ```php $money->setValue(100); ``` Set the [currency code](https://docs.dojo.tech/explore/data-types#country) (for example, GBP for British Pounds). ```php $money->setCurrencyCode("GBP"); ``` Set the amount in the request: The `$money` item in this example should also be written in minor units. ```php $req->setAmount($money); ``` Use the client to create the payment intent by making a request to the payment gateway. The `paymentIntentsCreatePaymentIntent` method is called with the provided API version and the payment intent request object: ```php $paymentIntent = $client->paymentIntentsCreatePaymentIntent(\Dojo_PHP\API_VERSION, $req); ``` The `$paymentIntent` now contains the information about the created payment intent. For any requests, bugs, or comments, please [open an issue](https://github.com/dojo-engineering/Dojo.PHP/issues) or [submit a pull request](https://github.com/dojo-engineering/Dojo.PHP/pulls). --- ## SDKs >Check out our software development kits. [![](https://docs.dojo.tech/images/dojo-icons/AppleLogo.svg) **iOS** Integrating iOS SDK.](../mobile-integration/ios) [![](https://docs.dojo.tech/images/dojo-icons/AndroidLogo.svg) **Android** Integrating Android SDK.](../mobile-integration/android) [![](https://docs.dojo.tech/images/dojo-icons/Cube.svg) **.NET** Integrating .NET SDK.](dotnet-sdk) [![](https://docs.dojo.tech/images/dojo-icons/Cube.svg) **PHP** Integrating PHP SDK.](php-sdk) [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Need a hand?** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) --- ## Terms and Conditions ### About us We are Paymentsense Limited. Dojo is a trading name of Paymentsense Limited. Our registered office address is The Brunel Building, 2 Canalside Walk, London W2 1DG and our company number is 06730690. ### What's in these terms? These terms tell you the rules for using any of our application programming interfaces and documentation we make available, including the ‘Connect’ application programming interface **(Dojo Tools)** on this website or any of our other websites or applications. If you access or use any Dojo Tool, that access or use is subject to these terms and you accept these terms. If you are an electronic point-of-sale partner and have a separate agreement with us relating to the Dojo Tools, any terms in that separate agreement which conflict with those terms shall prevail. ### Your access and use We grant you a limited, non-exclusive, non-transferrable right to use the Dojo Tools for the sole purpose of maintaining an integration between your (or the third party you re-sell the services of) software and our payments services. You acknowledge that we are the owner of the Dojo Tools and retain all rights (including intellectual property rights) in and to the Dojo Tools. ### Code of Conduct You agree: (1) you will not make any misrepresentations to or mislead any third party; (2) you will avoid any conflict of interest or engage in any intentional unethical conduct; and (3) you will not cause any reputational harm to us. ### Responsibilities and Limitations In order to use and access our Dojo Tools, you must have or create an account with us. You will keep all credentials secure and shall use the credentials as your sole means of accessing our documentation. You may not share your account credentials with third parties. You shall not: (a) sell, rent, lease, sublicense or redistribute the Dojo Tools to any third party; (b) use the Dojo Tools for any unlawful or illegal purpose; (c) use the Dojo Tools to create any competitive product; (d) seek to commercialise the Dojo Tools; (e) place or enable the placement of any virus, malware or other code on the Dojo Tools; (f) hold yourself out as our agent. ### Liability We provide the Dojo Tools to you on an “as-is” basis, which means that we make no warranties or representations, either express or implied, as to the accuracy, reliability or completeness of the Dojo Tools. To the maximum extent permitted under applicable law, we disclaim all such warranties and representations. ### Indemnity You agree to indemnify us against all claims, losses, costs, expenses and liabilities we may suffer or incur that arise from or relate to: (a) your use (or any third party’s use via you) of the Dojo Tools; and (b) any breach of these terms by you. ### Termination We may terminate these terms and your use of the Dojo Tools at any time without notice. If we exercise this right, you must immediately cease using the Dojo Tools. If any other agreement we have with you in relation to the integration between our Dojo Tools and you terminate or expires, these terms will also automatically expire. Any rights you have to use the Dojo Tools will expire too. ### Modification We may update these terms at any time by updating this webpage. We do not have to give you any notice of this and your continued use of the Dojo Tools will be deemed acceptance of any changes that we make. ### Governing law These terms and any non-contractual obligations arising out of or in connection with them are governed by English law. You and we submit to the exclusive jurisdiction of the English courts. --- ## Test card numbers >Use the information on this page to test your integration. Dojo issues physical point-of-sale test cards to test [in-person payments](https://docs.dojo.tech/payments/accept-payments/in-person-payments/introduction) integrations. Alternately, if you are testing [online payments](https://docs.dojo.tech/payments/accept-payments/online-payments/introduction) integrations, you can use the virtual test card values below: > **Info:** The test card numbers are only valid for the Dojo sandbox environment. > > > In order to test your site, use the test cards with your test [API key](https://docs.dojo.tech/explore/api-keys). Any address and cardholder name can be used with the test cards. > > --- > > ## Versioning > > The Dojo Payments API uses the YYYY-MM-DD API version scheme. The current `version` header must be passed as part of all API calls. > > When you make the first API request, using the current date in the `version` header will fetch the latest available version. > > ## Breaking changes > > Breaking or backwards-incompatible changes include: > > - Changing the URL format. > - Changing parameters from non-mandatory to mandatory. > - Changing the type of a parameter. > - Changing authentication mechanism. > - Adding new mandatory request parameters to existing API methods. > - Removing or renaming a resource, field, method or an enum value. > > If we make breaking changes to the API, we release new, dated versions. We don't change your version, if you want to use a new version you have to change the version yourself. > > ## Non-breaking changes > > The following types of changes don't qualify as breaking changes, this list isn't exhaustive: > > - Adding new HTTP headers. > - Adding new values to an enum if there is a default defined. > - Adding new HTTP methods to existing resources. > - Adding new non-mandatory request or response parameters to existing API methods. > - Changing parameters from mandatory to non-mandatory. > > ## How to upgrade API > > When we release a new API version, you can choose to upgrade to gain access to new features. To change the API version you need to change the `version` header. > > When non-breaking changes are implemented into the current API version, these features will become available without needing an upgrade. > > --- > > ## Webhooks > > Learn how to get notified of any changes in your payments' data. > > Webhooks allow your application to receive notifications when certain events occur. For example, when a payment status is updated, Dojo will make a POST request to your URL and let you know about it. You can create 1 webhook for each event. Use the [Webhooks API](https://docs.dojo.tech/api#tag/Webhooks) to specify which events you would like to be notified about. > > Every webhook from Dojo includes a `dojo-signature` header. You can use this to verify that the data is coming from Dojo. > > **Tip:** Dojo sends this header as `Dojo-Signature`. Header names are case-insensitive by specification, but your server environment might expose them differently. Some frameworks or languages may automatically lowercase header names. Make sure to test and verify how headers are accessed in your environment to avoid integration issues. ## Response handling When handling server code webhook calls, Dojo does the following: - Accepts any `2xx` HTTP status code responses as a confirmation of successful delivery of the webhook message. - Interprets `4xx` or `5xx` HTTP status code responses as an error and re-attempts delivery for a limited number of times. ## Create webhooks Use the following instructions to create webhooks by using our API. You can also manage webhooks in the [Developer Portal](https://docs.dojo.tech/explore/portal#webhooks). To start using webhooks, you need: 1. [Choose which events to subscribe to](https://docs.dojo.tech/explore/changelog#step-1-choose-which-events-to-subscribe-to). 2. [Enable the webhook using the webhook endpoint](https://docs.dojo.tech/explore/changelog#step-2-enable-the-webhook). 3. [Verify Dojo webhooks](https://docs.dojo.tech/explore/changelog#step-3-verify-dojo-webhooks). 4. [Go live](https://docs.dojo.tech/explore/changelog#step-4-go-live). ### Before you start Before you begin, make sure you have followed the [Getting started guide](https://docs.dojo.tech/payments/getting-started) and get your API keys. Webhooks API use the same Basic Authentication as Dojo API. For the test environment, use your secret key with the prefix `sk_sandbox_`. ### Step 1. Choose which events to subscribe to You can have a list of all events by sending a `GET` request to Dojo's webhooks endpoints. ```GET /webhooks/events``` We recommend subscribing to the `payment_intent.status_updated` event to receive updates on changes in the status of your payment intents. For a complete list of available events and their payloads, see [Available webhooks](https://docs.dojo.tech/explore/changelog#available-webhooks). ### Step 2. Enable the webhook You can turn on webhooks either via the developer portal (https://developer.dojo.tech) or using the APIs. To enable a webhook using the API, use the endpoint below: ``` POST /webhooks ``` In your request, include: * `events`: the list of events you would like to subscribe to. For the list of the events, see [Available webhooks](https://docs.dojo.tech/explore/changelog#available-webhooks). * `url`: the endpoint the Dojo servers will send notifications to. The endpoint must be accessible from the public internet for the webhook to work. It must be an HTTPS endpoint as well. If you want to test webhooks before you create or configure a live service, you can use one of several request logging sites, for example, [WebHook Tester](https://webhook.site/). Alternatively, use a service like [ngrok](https://ngrok.com/). Here's an example of how to subscribe to the `payment_intent.status_updated` event: ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/webhooks \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Content-Type: application/json' \ --header 'Version: 2024-02-05' \ --data '{ "events": ["payment_intent.status_updated"], "url": "https://example.com/incoming-events" }' ``` For the full API specification, see the [API reference](https://docs.dojo.tech/api/#tag/Webhooks). ### Step 3. Verify Dojo webhooks To verify the authenticity of the webhook, you need to digest the received payload body by using [HMAC-SHA256](https://en.wikipedia.org/wiki/HMAC) with your `secret.value` as a key. If the result matches the one that you received in the `dojo-signature` header, then the webhook is authentic. For example: * for the following request body payload: :::warning In order to do a proper calculation, the JSON in the example below needs to be formatted without any spaces or line breaks. ``` json { "id": "evt_hnnHxIKR_Uy6bhZCusCltw", "event": "payment_intent.created", "accountId": "acc_test", "createdAt": "2022-02-01T13:07:41.8667859Z", "data": { "paymentIntentId": "pi_vpwd4ooAPEqyNAQe4z89WQ", "paymentStatus": "Created", "captureMode": "Auto" } } ```` * where the secret to calculate the signature was: `PDYkJQq6sESYHp_zJuTTBQ` * the signature header would be: `sha256=4B-49-F8-FE-25-A7-E6-7D-00-4F-A7-9C-F8-0B-63-00-C7-77-B4-F2-2D-E5-E1-22-84-FA-04-18-50-A1-76-FD` Below are examples in Python and C# to verify webhooks: ```py from hashlib import sha256 from flask import Flask, jsonify, request app = Flask(__name__) WEBHOOK_SECRET = "PDYkJQq6sESYHp_zJuTTBQ" def build_dojo_signature(payload: bytes, secret: str) -> str: digest = hmac.new( secret.encode("utf-8"), msg=payload, digestmod=sha256, ).digest() return "sha256=" + "-".join(f"{byte:02X}" for byte in digest) @app.route('/webhook', methods=['POST']) def webhook(): payload = request.get_data(cache=False) signature_header = request.headers.get('dojo-signature') if not signature_header: print('Missing dojo-signature header.') return jsonify(success=False), 400 expected_signature = build_dojo_signature(payload, WEBHOOK_SECRET) if not hmac.compare_digest(signature_header, expected_signature): print('Invalid signature.') return jsonify(success=False), 400 try: event = json.loads(payload.decode("utf-8")) except json.JSONDecodeError as error: print(f'Invalid webhook payload: {error}') return jsonify(success=False), 400 print('Signature verified.') print(json.dumps(event, indent=2)) return jsonify(success=True) ``` ### Step 4. Go live If you want to test webhooks before you create or configure a live service, you can use one of several request logging sites, for example, [WebHook Tester](https://webhook.site/). Alternatively, use a service like [ngrok](https://ngrok.com/). When you are ready to go live, switch your secret key to production one with the prefix `sk_prod_` and check `url` that you provide. ## Available webhooks ### Payment intents webhooks * `payment_intent.status_updated` * `payment_intent.created` * `payment_intent.send-receipt` | Property | Type |Description | |-----|-----|-----| |`id` |string|Unique identifier for the event.| |`event` |string|The event type. Possible values are `payment_intent.status_updated`, `payment_intent.created`, `payment_intent.send-receipt`.| |`accountId` |string|Unique identifier for the account. | |`createdAt` |string date-time|The timestamp of the create date, in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) UTC format.| |`data` |object|Information regarding the payment.| |`data.paymentIntentId` |string|Unique identifier for the payment intent.| |`data.paymentStatus` |string|Current status of the payment intent. Possible values are `Created`, `Authorized`, `Captured`, `Reversed`, `Refunded`, `Canceled`.| |`data.captureMode` |string|The type of capture for the payment. Possible values are `Auto`, `Manual`.| ## Webhooks and events management You can manage webhooks and events by using our API: * [Retrieve a list of all events](https://docs.dojo.tech/api#operation/Webhooks_GetAllWebhooks). * [Retrieve a list of all subscriptions that you have](https://docs.dojo.tech/api#operation/Webhooks_GetAlSubscriptions). * [Create a new subscription for chosen events](https://docs.dojo.tech/api#operation/Webhooks_Subscribe). * [Update your subscription details](https://docs.dojo.tech/api#operation/Webhooks_SubscribeUpdate). * [Delete a subscription](https://docs.dojo.tech/api#operation/Webhooks_DeleteSubscriptions). * [Retrieve a list of secrets for the subscription](https://docs.dojo.tech/api#operation/Webhooks_GetSecrets). * [Generate a new secret](https://docs.dojo.tech/api#operation/Webhooks_GenerateSecret). * [Activate a secret](https://docs.dojo.tech/api#operation/Webhooks_ActivateSecret). * [Delete a secret](https://docs.dojo.tech/api#operation/Webhooks_DeleteSecret). --- ## Introduction(Bookings) # Dojo Bookings Dojo bookings is a crucial part of Dojo's **Restaurant Management System (RMS)**. It is designed to provide best in class, integrated, management tools to businesses. **Dojo Bookings** uses all entities within the [EPOS Data API](https://docs.dojo.tech/api-hosting/epos-data) to retrieve and manipulate data on the POS. **Dojo Bookings** infers availability from the information recieved by the **POS** in near-real time, as such, the integration allows a seamless, efficient and importantly an automated way of organising bookings and directing guests to venues with availability. ### Core Components >The core components needed to support Dojo Bookings | **Features** | **Description** | | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Orders` | The Order entity represents the core component of the Ordering API, containing all relevant information about an order placed by customers at a given location. An order can consist of multiple items, each with details like status, quantity, price, and applied modifiers. Dojo products create, modify and retrieve orders on the POS via the EPOS Data component of the Dojo API. | | `Parties` | The **Parties** entity represents a group seated in the venue, and should uniquely identify them in the POS for the entire duration of their stay. **Dojo Bookings** infers availability by the presence of a party at a table. Each party can include additional details such as deposits, special requests and allergen information. A Table may have one party associated to it at any one time, where a **Party** may have multiple tables and orders associated. The partyId should be unique and not match any other current party, you may reuse ids for parties that are now deleted. | | `Reservations` | The Reservation entity represents an upcoming party or booking. Reservations may be created, updated and deleted by Dojo products. Once a reservation has been seated within the venue, it becomes a party. The POS may also create a reservation, however, you should be aware that the POS may not have full access to the availability and schedules set up on **Dojo Bookings**. Once a reservation is seated, a party is created that is linked to that reservation - but the reservation itself continues to exist (unchanged) as before . | | `Tables` | The Table entity represents a physical place within a location and/or area where customers are designated. Tables are mostly static, but expected to change if there are physical layout changes at a location. Tables may have multiple active [orders](https://docs.dojo.tech/core-concepts/orders) at any one time. | | `Areas` | The **Area** entity represents physical areas within a location. Examples of areas would be "dining area", "beer garden" and "upstairs". ## Capabilites In the Dojo EPOS Data API, **capabilities** represent specific actions that the POS system can perform. These capabilities are linked to corresponding API endpoints in the POS system. By defining these capabilities, the POS system communicates to Dojo which features are supported and accessible. See [Registering capabilities](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities) for how each capability is registered with Dojo. **Registering a capability:** the heading for each capability below (for example `SearchOrders`, `GetOrderById`, `CreateOrderLock`, `RecordOrderPaymentById`) is the exact `name` value to send in the body of `PUT /epos/integrations/rest` or `PUT /epos/integrations/ws`. The version is sent alongside as a separate field (`"version": "v1"`); appending `V1` to the heading gives you the wire-level method Dojo invokes after registration (for example `RecordOrderPaymentByIdV1`). See [Registering capabilities](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities) for the full body schema. For backwards compatibility, registration also accepts the four legacy names `GetOrderBill`, `RecordOrderPayment`, `UpdatePartyById`, and `UpdateReservationById` — they are equivalent to `GetOrderBillById`, `RecordOrderPaymentById`, `UpdateParty`, and `UpdateReservation` respectively. New integrations should prefer the wire-aligned form shown in the headings below. The below capabilites are needed to support all aspects of the **Dojo Bookings** integration: ## Reservations ### CreateReservation > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Reservations > See OpenAPI spec for CreateReservationV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-CreateReservationV1_Request This capability allows for the creation of a new **reservation** within the POS system. This enables the creation of bookings on the POS by Dojo products. ### UpdateReservation > See OpenAPI spec for PUT endpoint details: https://docs.dojo.tech/epos-data/api#tag/Reservations/operation/v1-put-reservations-reservationId > See OpenAPI spec for UpdateReservationV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-UpdateReservationV1_Request This capability allows Dojo to update **reservations** on the POS. For example, this could be changes to the reservation's covers, time-slot or table IDs. ### GetReservationById > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/epos-data/api#tag/Reservations/operation/v1-get-reservations-reservationId > See OpenAPI spec for GetReservationByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-GetReservationByIdV1_Request This capability allows Dojo to retrieve up-to-date information from the POS about a specific **reservation** such as the start-time, end-time and any booked table IDs. ### SearchReservations > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Reservations/operation/v1-search-reservations > See OpenAPI spec for SearchReservationsV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-SearchReservationsV1_Request This capability allows Dojo to retrieve **reservations** from a POS and can include filters such as table Id and time slot. ### DeleteReservationById > See OpenAPI spec for DELETE endpoint details: https://docs.dojo.tech/epos-data/api#tag/Reservations/operation/v1-delete-reservations-reservationId > See OpenAPI spec for DeleteReservationByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-DeleteReservationByIdV1_Request This capability allows Dojos to delete a specific **reservation** by using the reservation Id. ## Parties ### CreateParty > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Parties > See OpenAPI spec for CreatePartyV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-CreatePartyV1_Request This capability allows the creation of a new **Party** within the POS system. It is essential for assigning parties to a table and storing relevant order details. ### UpdateParty > See OpenAPI spec for PUT endpoint details: https://docs.dojo.tech/epos-data/api#tag/Parties/operation/v1-put-parties-partyId > See OpenAPI spec for UpdatePartyV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-UpdatePartyV1_Request This capability allows Dojo to update the POS with additional **party** information given after initial booking. For example, this could be the party's allergen requirements in the form of guestRequests, a change in booking time or a new expected end-time. ### GetPartyById > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/epos-data/api#tag/Parties/operation/v1-get-parties-partyId > See OpenAPI spec for GetPartyByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-GetPartyByIdV1_Request This capability allows Dojo to retrieve up-to-date information about a specific **party** seated at a table, such as the unique ID, table ID and status. ### SearchParties > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Parties/operation/v1-search-parties > See OpenAPI spec for SearchPartiesV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-SearchPartiesV1_Request This capability allows Dojo to retrieve parties from a POS. By default, the POS should not return parties where `endTime` is set, including them only where `completedOnly` is "true". ### DeletePartyById > See OpenAPI spec for DELETE endpoint details: https://docs.dojo.tech/epos-data/api#tag/Parties/operation/v1-delete-parties-partyId > See OpenAPI spec for DeletePartyByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-DeletePartyByIdV1_Request This capability allows Dojos Epos Data API to delete a specific **party** by using the party Id. ## Orders ### GetOrderById > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-get-orders-orderId > See OpenAPI spec for GetOrderByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-GetOrderByIdV1_Request This capability enables Dojo to retrieve detailed information about a specific order using its unique order ID. This is crucial for order tracking and status updates. ### SearchOrders > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/paths/~1v1~1orders~1search/post > See OpenAPI spec for SearchOrdersV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-SearchOrdersV1_Request This capability enables searching for orders based on various criteria. It supports filtering and pagination to help Dojo products efficiently find orders within the POS system. Each Dojo product has different requirements on what filters must be implemented which can be found on the product documentation page(s). ## Tables ### SearchTables > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Tables/operation/v1-search-tables > See OpenAPI spec for SearchTablesV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-SearchTablesV1_Request This capability enables searching for Tables from the POS system. ## Areas ### ListAreas > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/epos-data/api#tag/Areas/operation/v1-list-areas > See OpenAPI spec for ListAreasV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-ListAreasV1_Request This capability enables listing areas from the POS system. ### Source of truth The POS serves as the authoritative source for all its data. Dojo products, such as **Bookings**, can request to modify this data via the EPOS Data API, but the responsibility lies with the POS to invalidate any inappropriate requests. For instance, if a Dojo product attempts to update an order via the EPOS Data API, the POS should apply any business logic validation to ensure that the order is allowed to be updated in this way. --- ## Flows(Bookings) > This section covers the step-by-step flows to integrate with Dojo Bookings > **Info:** Where an action is taken on the **POS** or **Dojo Bookings**, there is an expected action to update the other system. This API is bidirectional to allow both parties to be in sync in near real time. >The step-by-step guides below change depending on which flow diagram you are looking at. RMS to POS indicates the action was taken on Dojo Bookings platform, whereas POS to RMS indicates the action was taken on the POS. This flow diagram demonstrates how **Dojo Bookings** will interact with the POS system for seating guests, when the action of seating them is performed on **Dojo Bookings** software ![Payment Intent Flow](https://docs.dojo.tech/images/rms-to-pos-flow.png) **Flow diagram: Rms To Pos Flow** ```mermaid sequenceDiagram participant RMS participant B as DOJO Backend participant EPOS Note over RMS: Reservation is made ahead of time RMS->>B: Reservation is generated B->>EPOS: CreateReservation (POST v1/reservations) EPOS-->>B: 200 OK + {responseBody} Note over RMS: Reservation is amended RMS->>B: Reservation is amended B->>EPOS: UpdateReservation (PUT /v1/reservations/{id}) EPOS-->>B: 200 OK + {responseBody} Note over RMS: Reservation is seated RMS->>B: Reservation is given a party ID B->>EPOS: CreateParty (PUT /v1/parties) EPOS-->>B: 200 OK + {responseBody} Note over RMS: Party is amended using RMS RMS->>B: Updated details are provided B->>EPOS: UpdateParty (POST /v1/parties) EPOS-->>B: 200 OK + {responseBody} ``` ### Step 1: Reservation is made ahead of time > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Parties > See OpenAPI spec for CreateReservationV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-send-CreatePartyV1_Request A reservation is made ahead of time by a customer using Dojo Bookings platform. This reservation will be sent to the POS on the day the reservation has been made for, containing information such as `reservationId`, `startTime` and `tableId` ### Step 2: (Optional) There is an update to the reservation > See OpenAPI spec for PUT endpoint details: https://docs.dojo.tech/epos-data/api#tag/Parties > See OpenAPI spec for UpdateReservationV1 endpoint details: https://docs.dojo.tech/epos-data/api#tag/Reservations/operation/v1-put-reservations-reservationId The customer has the ability to amended their booking, if they update details such as `startTime`, `covers`, they have additional `guestRequests` or a new `tableId` has been assigned. Dojo bookings will send this to the POS ahead of time ready for the guests to arrive. ### Step 3: Reservation is seated using Dojo Bookings, creating a Party > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Parties > See OpenAPI spec for CreatePartyV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-send-CreatePartyV1_Request Once the guests arrive, the venue hosts seats them at the predefined table. Once seated, Dojo Bookings will generate a `dojoPartyId` and use the createParty endpoint to update the POS, this request will contain the reservationId so it can be easily be attributed to the correct booking. Dojo provides the dojoPartyId for reference which the POS may use in place of generating a new internal ID, however, as we cannot guarantee uniqueness to the existing set on the POS then this is not recommended. This step is also applicable if there is a walk in seated, the only difference is the exclusion of the `reservationId` in this scenario. ### Step 4: (Optional) Party is updated using Dojo Bookings > See OpenAPI spec for PUT endpoint details: https://docs.dojo.tech/epos-data/api#tag/Parties > See OpenAPI spec for UpdatePartyV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-send-UpdatePartyV1_Request If an update to the party is made, this allows Dojo to update the POS with additional party information, for example, this could be the party's allergen requirements in the form of guestRequests, a change in booking time, a new expected end-time or a new tableId has been assigned to the party. ### Step 5: (Optional) Reservation is cancelled > See OpenAPI spec for DELETE endpoint details: https://docs.dojo.tech/epos-data/api#tag/Reservations/operation/v1-delete-reservations-reservationId > See OpenAPI spec for DeleteReservationByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-send-DeleteReservationByIdV1_Request In the event a guest cancels their reservations, **Dojo Bookings** will issue a DELETE, to **/v1/reservations/\{reservationId\}**. If there is a party already associated, we will also issue a DELETE to **/v1/parties/\{partyId\}** This flow diagram demonstrates how **Dojo Bookings** will interact with the POS system for seating guests when the action of seating them is performed on the **POS software**. ![Payment Intent Flow](https://docs.dojo.tech/images/pos-to-rms-flow.png) **Flow diagram: Pos To Rms Flow** ```mermaid sequenceDiagram participant RMS participant B as DOJO Backend participant POS Note over RMS: Reservation is made ahead of time RMS->>B: Reservation created B->>POS: CreateReservation (POST v1/reservations) POS-->>B: 200 OK + {responseBody} Note over POS: Reservation is amended POS->>B: UpdateReservation Event (POST REST /epos/events) B->>POS: GetReservationById (GET /v1/reservations/{id}) POS-->>B: UpdateReservation (200 OK + response) B-->>RMS: Reservation updated on the RMS Note over POS: Reservation is seated on the POS POS->>B: UpdateParty Event (POST /epos/events) B->>POS: GetPartyById (GET v1/parties/{id}) POS-->>B: 200 OK + response B->>RMS: RMS updated with PartyId & info Note over POS: Party is updated (e.g. Moved table) POS->>B: UpdateParty Event B->>POS: GetPartyById POS-->>B: 200 OK + response B->>RMS: RMS updated with PartyId & info Note over POS: Order is updated (e.g. Items added) POS->>B: UpdateOrder Event B->>POS: GetOrderById (GET v1/orders/{id}) POS-->>B: 200 OK + response ``` ## ### Step 1: Reservation is made ahead of time > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Parties > See OpenAPI spec for CreateReservationV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-send-CreatePartyV1_Request A reservation is made ahead of time by the customer using **Dojo Bookings** platform. This reservation will be sent to the POS up to 24 hours ahead of time or on the day the reservation has been made for, containing information such as `reservationId`, `startTime` and `tableId`. A reservation can also be created on the **POS**, in this instance a [POS Event](https://docs.dojo.tech/core-concepts/pos-events) should be submitted using `eventType:ReservationUpdated`. Dojo Bookings will then call a GET reservationById where a new booking will be generated for any unknown reservation IDs. ### Step 2: (Optional) There is an update to the reservation, made on the POS ##### This is a call made by the POS to the Dojo API > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api#tag/Events/paths/~1epos~1events/post If the update to the reservation is recorded on the POS, then a [POS Event](https://docs.dojo.tech/core-concepts/dojo-events) should be submitted using `eventType:ReservationUpdated`, these events are notifications about changes relating to entities which are owned by the POS system and allow Dojo products to be able to react in near real time. This request must include the `reservationId`. ### Step 3: Dojo Bookings reacts to the event and confirms the updated details with the POS. > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/epos-data/api#tag/Reservations/operation/v1-post-reservations > See OpenAPI spec for GetReservationV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-send-GetReservationByIdV1_Request Dojo will call the POS to confirm the updated reservation details using the reservationId, the response should include any and all up to date information on the reservation. ### Step 4: The reservation is seated on the POS ##### This is a POS to Dojo API call > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api#tag/Events/paths/~1epos~1events/post When the reservation is seated and recorded on the POS, then a [POS Event](https://docs.dojo.tech/core-concepts/dojo-events) should be submitted using `eventType:partyUpdated`, these events are notifications about changes relating to entities which are owned by the POS system and allow Dojo products to be able to react in near real time. This request must includes a `partyId` which is designated by the POS and must correspond to the POS internal ID of the reservation that it corresponds to. This field must not be changed after creation. ### Step 5: Dojo Bookings reacts to the event and confirms the Party details with the POS. > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/epos-data/api#tag/Reservations/operation/v1-get-reservations-reservationId > See OpenAPI spec for GetPartyByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-send-GetPartyByIdV1_Request Dojo will call the POS to confirm the updated party details using the `partyId`, the response should include any and all up to date information on the party. The response from the [GET Party by Id](https://docs.dojo.tech/epos-data/api#tag/Parties/operation/v1-get-parties-partyId) call will include details such as `tableId`, `status`, `startTime` and any `hostNotes` related to the party. If the party has ended, the `endTime` field should be set and stored for Dojo products to retrieve. ### Step 6: (Optional) Party details have been updated on the POS ##### This is a POS to Dojo API call > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api#tag/Events/paths/~1epos~1events/post In the event where a party has been updated, for example, moved tables in the venue then a POS Event should be submitted using `eventType:partyUpdated` ### Step 7: Dojo Bookings reacts to the event and confirms the Party details with the POS. > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/epos-data/api#tag/Reservations/operation/v1-get-reservations-reservationId > See OpenAPI spec for GetPartyByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-send-GetPartyByIdV1_Request Dojo will call the POS to confirm the updated party details using the `partyId`, the response should include any and all up to date information on the party. This will then be relayed to RMS and the details updated. The response from the [GET Party by Id](https://docs.dojo.tech/epos-data/api#tag/Parties/operation/v1-get-parties-partyId) call will include details such as `status`, `startTime` and any new `tableIds` related to the party. In case of the update being the party has finished, the `endTime` should be updated and stored so that **Dojo Bookings** can obtain the `endTime` of the visit. ### Step 8: The order details are updated on the POS ##### This is a POS to Dojo API call > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api#tag/Events/paths/~1epos~1events/post In the event where an order has been updated, for example, it has been paid or items have been added to the table. A POS Event should be submitted using `eventType:orderUpdated`. This will provide the orderId assigned by the POS to *Dojo Bookings* ### Step 9: Dojo Bookings reacts to the event and confirms the Order details with the POS. > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-get-orders-orderId > See OpenAPI spec for GetOrderByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-send-GetOrderByIdV1_Request Dojo will call the POS to confirm the updated Order details using the `orderId`, the response should include any and all up to date information on the order. In the getOrderbyId response, there should be a partyId in the `details.dineIn` object, this allows Dojo Bookings to attribute the order to the correct party. ### Step 10: (Optional) Reservation is deleted on the POS > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/api#tag/Events/paths/~1epos~1events/post If at anytime a user needs to delete a reservation using the POS then a [POS Event](https://docs.dojo.tech/core-concepts/pos-events) should be submitted using `eventType:ReservationUpdated` after the booking has been deleted. **Dojo Bookings** will then call `getReservationById` where the POS should return a `status code 404: Not found`. Dojo Bookings will then delete the reservation from its records as it no longer exists. --- ## API explorer > This section is a library of all APIs built by Dojo. You can explore the APIs and their endpoints to understand how they work. ## Hosted by Dojo These APIs are **Dojo-hosted**, which means they are fully managed and hosted by Dojo. Typically, includes public-facing REST APIs, like payment intents for face-to-face or online payments. Dojo-hosted APIs are integrated directly into our product ecosystem. [**Dojo API** Manage intents, Webhooks, customer operations, Pay at Counter, and remote payments.](https://docs.dojo.tech/api) [**Payments API** The legacy remote payments API.](https://docs.dojo.tech/payments/api/) ## Hosted by partners A **partner-hosted** API has had its specification defined by Dojo, but it must be hosted and managed by a development partner. Dojo will interact with this API by calling it when needed, but the responsibility for maintaining and running it lies with you. [**EPOS Data API** Websocket protocols for EPOS data operations.](https://docs.dojo.tech/epos-data/ws/api) [**EPOS Data API** REST protocols for EPOS data operations.](https://docs.dojo.tech/epos-data/api) [**Tables API** The legacy Pay at Table API.](https://docs.dojo.tech/tables/api/) --- ## Changelog > Stay updated with the latest releases of the Dojo API. This changelog highlights the latest and breaking changes in the Dojo API. Each new release version aligns with a date. This approach allows for a clear and chronological representation of our API versions, making it easier to track changes and updates over time. > **Info:** If you want to integrate with the Dojo API for the first time or you want to upgrade from the previous version, contact us by [**email**](mailto:partnertech@dojo.tech) or [**GitHub**](https://github.com/orgs/dojo-engineering/discussions). > > > ## 2026-27-02 > > ### Breaking changes > - This version introduces no breaking changes. > > ### What's new? > - Added a new property `isNotOnlineCheckout` where you need to set it to `true` to accept payments links without the requirement for online checkout permissions. When set to `false` or not provided, full online checkout permissions will be required to take a payment via payment links. > > --- > > ## 2025-09-10 > > ### Breaking changes > - This version introduces no breaking changes. > > ### What's new? > Several fields have been converted from **enums** to **strings** to allow future flexibility: > > - When registering or fetching an integration: `capabilities` > - When creating an event: `eventType` > - When creating a setup intent: `merchantInitiatedTransactionType` > - When creating a payment intent: > - `paymentMethods` > - `paymentDetails.card.entryMode` > - `paymentDetails.card.verificationMethod` > - `merchantConfig.supportedPaymentMethods.cardSchemes` > - `merchantConfig.supportedPaymentMethods.wallets` > - When creating a terminal session: `notificationEvents` > > --- > > ## 2024-02-05 > > ### Breaking changes > - Renamed itemLines.**caption** to itemLines.**name**. > - itemLines.**amountTotal** is a required field. > - Replaced `transactionSource: MOTO` with `cardHolderNotPresent` which is boolean. > - Added a new property `generateRemoteToken` where you need to set it to `true` to accept online payments immediately. When set to `false`, the `clientSessionSecret` will not be created. This impacts only online payments. This does not impact virtual terminals, payment links, and mobile SDKs. > > ### What's new? > - Added a new path `Terminals` which will accept in-person, at-counter payments using the following endpoints: > - POST [/terminal-sessions](https://docs.dojo.tech/api#tag/Terminal-sessions/operation/TerminalSession_Create) > - GET [/terminals](https://docs.dojo.tech/api#tag/Terminals/operation/Terminals_ListTerminals) > - GET [/terminals/{terminalId}](https://docs.dojo.tech/api#tag/Terminals/operation/Terminals_GetTerminal) > - GET [/terminal-sessions/{terminalSessionId}](https://docs.dojo.tech/api#tag/Terminals/operation/Terminals_GetTerminal) > - PUT [/terminal-sessions/{terminalSessionId}/signature](https://docs.dojo.tech/api#tag/Terminal-sessions/operation/TerminalSession_Signature) > - PUT [/terminal-sessions/{terminalSessionId}/cancel](https://docs.dojo.tech/api#tag/Terminal-sessions/operation/TerminalSession_Cancel) > > > > [![](https://docs.dojo.tech/images/dojo-icons/TerminalWindow.svg) **API reference** Learn about the API and integrate with API endpoints.](/api/#tag/Terminals) > > [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Support** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) > > > > --- > > ## EPOS Data API Integration Explorer > > Use the explorer below to see which capabilities are needed to support an integration with each Dojo product. Some of the core concepts are used across multiple integrations to provide the maximum uptake for the least amount of development. > > > > --- > > ## EPOS Data > > > This section contains the REST version and Websockets version of the EPOS Data API. > > The EPOS Data API offers two integration methods for connecting the EPOS system with Dojo: **REST** and **Websockets**. These methods > can be used separately or in combination depending on your system architecture and data accessibility needs. > > ## [REST](https://docs.dojo.tech/epos-data/api) > > The **REST API** is ideal for centralized architectures where the EPOS data is hosted on a centralized server. Dojo > can interact with the server using standard HTTP methods to access or modify data. > > Recommended for: > - Centralized EPOS data hosted on a server. > - Stateless communication, where each API request is independent. > - Asynchronous data access and batch processing. > > ## [Websockets](https://docs.dojo.tech/epos-data/ws/api) > > Visit the [getting started](https://docs.dojo.tech/explore/epos-data/getting-started) page for instructions on establishing a WebSockets connection. > > The **Websockets API** is best for environments where EPOS data resides locally and must be shared with Dojo in real-time. It maintains > a persistent connection between the EPOS and Dojo to enable low-latency, continuous data transmission without repeated polling. > > Recommended for: > - On-premise EPOS data that requires real-time synchronization. > - Persistent, low-latency communication like live transaction updates. > > ## Dojo API Key > > An [API Key](https://docs.dojo.tech/development-resources/api-keys) is required to access the EPOS Data API: > > - You need a key that starts with `sk_sandbox_` to access to the sandbox environment. > - You need a key that starts with `sk_prod_` to access the production environment. > > In the following examples, `{{API_KEY}}` is used as a placeholder for the actual API Key. > > ## Registering capabilities > > Register your EPOS Data API endpoints as capabilities in the [Dojo API](https://docs.dojo.tech/api) so Dojo knows which functions are available. **Registration is mandatory**: until you register a capability, Dojo will not invoke it on your EPOS, even if your WebSocket connection is open and your REST endpoint is reachable. > > * PUT [/epos/integrations/rest](https://docs.dojo.tech/api#tag/Capabilities/paths/~1epos~1integrations~1rest/put) (REST) > * PUT [/epos/integrations/ws](https://docs.dojo.tech/api#tag/Capabilities/paths/~1epos~1integrations~1ws/put) (WebSockets) > > The valid `capabilities[].name` values are the ones documented in [Core concepts](https://docs.dojo.tech/core-concepts/orders) — for example `SearchOrders`, `GetOrderById`, `CreateOrderLock`, `RecordOrderPaymentById`, `GetOrderBillById`, `ListAreas`. **The heading text on each capability page is the exact `name` to send in the registration body**; the version is sent alongside as `"version": "v1"`. Appending `V1` to the registration name gives the wire-level method that Dojo will invoke on your EPOS (for example `SearchOrdersV1`, `RecordOrderPaymentByIdV1`). > > Event-driven capabilities are registered per event type using a colon qualifier; each registered event type maps to the same `HandleEventV1` wire method: > > - `HandleEvent:payment_intent.created` > - `HandleEvent:payment_intent.status_updated` > > The full set of registerable capability names accepted today is: > > | Domain | Capability names | > | --- | --- | > | Orders | `CreateOrder`, `GetOrderById`, `CancelOrderById`, `SearchOrders`, `RecordOrderPaymentById`, `GetOrderBillById`, `AddOrderItems` | > | Order locking | `CreateOrderLock`, `DeleteOrderLock`, `ExtendOrderLock` | > | Order and Pay (preview) | `CalculateOrder`, `SubmitCalculatedOrder`, `SearchMenus` | > | Parties | `CreateParty`, `GetPartyById`, `UpdateParty`, `DeletePartyById`, `SearchParties` | > | Reservations | `CreateReservation`, `GetReservationById`, `UpdateReservation`, `DeleteReservationById`, `SearchReservations` | > | Tables & areas | `SearchTables`, `ListAreas` | > | Events | `HandleEvent:payment_intent.created`, `HandleEvent:payment_intent.status_updated` | > > **Note:** For backwards compatibility, the registration endpoint also accepts the legacy names `GetOrderBill`, `RecordOrderPayment`, `UpdatePartyById`, and `UpdateReservationById` — they're equivalent to `GetOrderBillById`, `RecordOrderPaymentById`, `UpdateParty`, and `UpdateReservation`. New integrations should use the wire-aligned form (the one shown in the table above).> **Note:** `AddOrderItems`, `CalculateOrder`, `SubmitCalculatedOrder`, and `SearchMenus` are accepted by `PUT /epos/integrations/{rest,ws}` today, but their request and response contracts are still being finalised. Don't register them in production until the corresponding REST/WS pages are published. If you're integrating with Order and Pay and need any of these, contact your Partnership Development Manager (PDM). You can view the currently registered capabilities using the following API call: ```curl curl --location 'https://api.dojo.tech/epos/integrations' \ --header 'Accept: application/json' \ --header 'software-house-id: my-place-curl' \ --header 'Authorization: Basic {{API_KEY}}' ``` This will return a list of registered capabilities. If no capabilities are registered, the response will be empty: ```json { "restIntegrations": [], "wsIntegrations": [] } ``` Once you've registered capabilities, the response includes one entry per integration with the capability list, the version Dojo will invoke, and an `updatedAt` timestamp: ```json { "restIntegrations": [], "wsIntegrations": [ { "createdAt": "2026-04-27T10:08:46.421Z", "capabilities": [ {"name": "SearchOrders", "version": "v1", "updatedAt": "2026-04-27T10:08:46.421Z"}, {"name": "GetOrderById", "version": "v1", "updatedAt": "2026-04-27T10:08:46.421Z"}, {"name": "RecordOrderPaymentById", "version": "v1", "updatedAt": "2026-04-27T10:08:46.421Z"}, {"name": "HandleEvent:payment_intent.created", "version": "v1", "updatedAt": "2026-04-27T10:08:46.421Z"}, {"name": "HandleEvent:payment_intent.status_updated", "version": "v1", "updatedAt": "2026-04-27T10:08:46.421Z"} ] } ] } ``` ### Example: registering `GetOrderById` on REST To register a capability (e.g., `GetOrderById`), you can use the following command: ```curl curl --location --request PUT 'https://api.dojo.tech/epos/integrations/rest' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'software-house-id: my-place-curl' \ --header 'Authorization: Basic {{API_KEY}}' \ --data '{ "capabilities": [ { "name": "GetOrderById", "version": "v1" } ], "auth": { "authType": "basic", "basic": { "username": "dojo", "password": "password" } }, "url": "https://f815-86-22-100-52.ngrok-free.app/some/path/v1/orders/{orderID}" }' ``` This command registers the `GetOrderById` capability on the REST adapter, making it accessible through the provided URL with basic authentication. ### Example: registering capabilities for WebSockets The WebSocket variant uses the same `capabilities` array but **does not** include `auth` or `url` — Dojo invokes the methods over the WebSocket connection your EPOS opens to `wss://eu.ws.dojo.tech/epos`. ```curl curl --location --request PUT 'https://api.dojo.tech/epos/integrations/ws' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'software-house-id: my-place-curl' \ --header 'Authorization: Basic {{API_KEY}}' \ --data '{ "capabilities": [ {"name": "ListAreas", "version": "v1"}, {"name": "SearchTables", "version": "v1"}, {"name": "SearchOrders", "version": "v1"}, {"name": "GetOrderById", "version": "v1"}, {"name": "GetOrderBillById", "version": "v1"}, {"name": "CreateOrderLock", "version": "v1"}, {"name": "ExtendOrderLock", "version": "v1"}, {"name": "DeleteOrderLock", "version": "v1"}, {"name": "RecordOrderPaymentById", "version": "v1"}, {"name": "HandleEvent:payment_intent.created", "version": "v1"}, {"name": "HandleEvent:payment_intent.status_updated", "version": "v1"} ] }' ``` Send the full list of capabilities you implement on every PUT — capabilities omitted from the body will not be routed to your EPOS until you re-register them. ## Using the EPOS tester tool > **Tip:** The EPOS tester tool is used to verify your [partner-hosted](https://docs.dojo.tech/api-explorer#hosted-by-partners) integration. Don't have access to the EPOS tester tool? Reach out to your Partnership Development Manager. The API reference for the EPOS tester tool can be found [here](https://docs.dojo.tech/epos-tester-tool/api/). Once you have registered your capabilities, you can test the integration using the **epos-tester-tool**. This service allows you to test individual API methods or entire transaction flows. It’s designed to facilitate development by letting you trigger Dojo calls programmatically and verify their correctness in real-time. For example, to list all available flows and their parameters, use the following request: ```curl curl --location 'https://api.dojo.tech/epos-tester-tool/flows' \ --header 'Accept: application/json' \ --header 'software-house-id: my-place-curl' \ --header 'Authorization: Basic {{API_KEY}}' ``` One such flow is `Get Order`, which you can trigger using this command: ```curl curl --location 'https://api.dojo.tech/epos-tester-tool/flows' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'software-house-id: my-place-curl' \ --header 'Authorization: Basic {{API_KEY}}' \ --data '{ "flow": "Get Order", "params": { "orderId": "testOrderID" } }' ``` The response is the bare flow ID as a quoted JSON string, for example: ```json "d00aa12a-7fb8-46a2-a22d-f4b560298353" ``` To check the status, run: ```curl curl --location 'https://api.dojo.tech/epos-tester-tool/flows/d00aa12a-7fb8-46a2-a22d-f4b560298353' \ --header 'Accept: application/json' \ --header 'software-house-id: my-place-curl' \ --header 'Authorization: Basic {{API_KEY}}' ``` The response will detail the status of the flow and list every step it went through. If a capability like `GetOrder` was not registered, the response will indicate failure and suggest registering the method: ```json { "finishedAt": "2024-09-19T15:03:23.529Z", "flowID": "d00aa12a-7fb8-46a2-a22d-f4b560298353", "flowName": "Get Order through EPOS Data API", "startedAt": "2024-09-19T15:03:21.226Z", "status": "FAILURE", "steps": [ { "additionalInformation": [ "GetOrder method not found", "Please register the GetOrder method on an EPOS Data API adapter" ], "finishedAt": "2024-09-19T15:03:23.524Z", "name": "Check whether GetOrder has been registered", "startedAt": "2024-09-19T15:03:21.51Z", "status": "FAILURE" } ] } ``` --- ## Opening a WebSockets connection >Obtain your API key and publish your first message. ## Step 1. Get your API keys Use the [Dojo developer portal](https://docs.dojo.tech/development-resources/portal) to receive your API key (`apiKey`). Reach out to your Partnership Development Manager (PDM) if you do not have access to the developer portal. This is required to receive and send messages to the API. ## Step 2. Open a WebSocket connection to the EPOS Data API To start integrating with the EPOS Data API, you can use our test endpoint. This endpoint allows you to simulate payments on the card machine, making it easier for you to develop and test your integration: ``` wss://eu.ws.dojo.tech/epos ``` Ensure you're using a WebSocket client that enables you to set the required headers: | Header Name | Description | |--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Authorization | Basic authorization is used to authenticate your requests to the API using your API key as the value, for example: Basic `$apiKey`. | | `reseller-id` (optional)| Identifies the reseller who sells software on behalf of the EPOS company. This value will be unique and provided by Dojo to each reseller. | | `software-house-id` | Identifies the EPOS company whose software is generating the request. This value shouldn't be configurable as it will remain the same for all customers using particular EPOS software. This value will be provided by Dojo. | All of these values will be provided by Dojo. If you're unsure about any of them, reach out to your PDM. > **Tip:** Despite the scheme name, do **not** base64-encode your API key. The literal value > `Basic ` (with the `sk_sandbox_` or `sk_prod_` key inserted as-is) is what > the gateway expects. ## Step 3. Confirm the WebSocket connection Ensure that you were able to successfully establish the WebSocket connection. Look out for any errors and reach out to your PDM if you require further assistance. ## Step 4. Register the capabilities you implement The connection alone is not enough — Dojo will only route a JSON-RPC method to your EPOS once you've **registered** that capability. Do this once, then update it whenever you add or remove a method. See [Registering capabilities](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities) for the request body and a worked example, and the per-capability pages under [Core concepts](https://docs.dojo.tech/core-concepts/orders) for the exact `name` value to register for each method. ## Connection lifecycle Once the WebSocket is open, Dojo multiplexes every JSON-RPC method invocation over the single connection. Keep these in mind when implementing the EPOS side: - **Long-lived connection.** The connection is expected to stay open. Dispatch each incoming JSON-RPC request to a handler concurrently and reply with a matching `id` on the same socket; the gateway correlates requests and responses by JSON-RPC `id`. - **Keepalive.** Send a WebSocket ping at least every 30 seconds when otherwise idle, and respond to incoming pings within a few seconds. Connections that go silent for several minutes may be closed by the gateway. - **Reconnect on close.** If the connection drops, reconnect with exponential backoff (e.g. 1s, 2s, 4s, capped at ~30s) and resume serving requests. In-flight requests are not replayed across reconnects — Dojo will retry on its side as needed, so handle requests **idempotently** based on the JSON-RPC `id` if you persist any side-effects before responding. - **One connection per `software-house-id` deployment.** Open one connection per logical EPOS instance. Multiple concurrent connections from the same `software-house-id` are not load-balanced; only one will receive routed requests at a time. - **HTTP/1.1 only.** WebSocket upgrade is not supported over HTTP/2. If your client library defaults to HTTP/2, force HTTP/1.1 for the handshake. ## Next steps You're now ready to start building your EPOS integration! --- ## Payments >Learn about Dojo's integration options for accepting payments. ## In-person payments Take payments [in-person](https://docs.dojo.tech/payments/payments/accept-payments/in-person-payments/introduction) when you integrate with an EPOS system. Customers at a café or retail shop are likely to pay at the counter, with the customer using the Dojo Go terminal and the merchant using the POS screen. In a table service setting, like a more traditional restaurant, the Dojo Go terminal is brought to the table and the transaction is processed solely using this device, without involving the POS. [![](https://docs.dojo.tech/images/dojo-icons/Bill.svg) **Pay at Counter** Take payments at an EPOS.](/payments/accept-payments/in-person-payments/pay-at-counter/introduction) [![](https://docs.dojo.tech/images/dojo-icons/PaymentCard.svg) **Pay at Table** Take payments at a customer's table.](/payments/pay-at-table/introduction) {/* import RecommendedIntegrationsNewOption2 from "@site/src/components/PaymentsIntegrations/RecommendedIntegrationsNewOption2" */} {/* */} ## Recommended online payments integrations ## Integrate with a plugin Dojo supports plugins to bring payments into your website. These plugins are officially built and maintained by our team. {/* ## Payment methods supported Dojo accepts payments in all major cards and wallets. */} ## Developer tools [![](https://docs.dojo.tech/images/dojo-icons/TerminalWindow.svg) **API reference** Learn about API and integrate with API endpoints.](/api) [![](https://docs.dojo.tech/images/dojo-icons/Copy.svg) **Sample integrations** Clone examples integrations.](https://github.com/dojo-engineering/dojo-samples) ## Connect with the community [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Support** Our support team is always happy to help with any questions you have.](https://support.dojo.tech/hc/en-gb) [![](https://docs.dojo.tech/images/dojo-icons/Message.svg) **Stack Overflow** Find answers to practical questions.](https://stackoverflow.com/questions/tagged/dojo.tech) --- ## Getting started >Generate API keys and make a first API call. > **Info:** Not a developer? Check out our [plugins](https://docs.dojo.tech/plugins). > > > ## Step 1. Log in to Dojo Developer Portal > > To get started, log in to [Dojo Developer Portal](https://developer.dojo.tech/login). You need to have a Dojo account. > > **Info:** - If you are a merchant, use `team members` to [invite your developer](https://account.dojo.tech/teams) to start the integration. > - If you are a developer, contact your merchant to receive an invite to register. > - If you are a partner, reach out to [Dojo support](https://support.dojo.tech/hc/en-gb). ## Step 2. Generate your API keys To submit payments, you'll be making API requests that are authenticated with an API key. ## Step 3. Make a test API call To verify that your key is working correctly, let's create a test API call. Copy the code below, replace the API key with your test API key (with the prefix `sk_sandbox_`), and run the code. ```bash # The sandbox API key passed in 'authorization' is public. # Don't submit any personally identifiable information in any requests made with this key. # Sign in to developer.dojo.tech to create your own private sandbox key and use that instead # for secure testing. curl -v --request POST \ --url https://api.dojo.tech/payment-intents \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic sk_sandbox_c8oLGaI__msxsXbpBDpdtwJEz_eIhfQoKHmedqgZPCdBx59zpKZLSk8OPLT0cZolbeuYJSBvzDVVsYvtpo5RkQ' \ --header 'Version: 2024-02-05' \ --data '{ "amount": { "value": 1000, "currencyCode": "GBP" }, "reference": "Order-0001", "paymentMethods": [ "Card", "Wallet" ] }' ``` If your account is set up correctly, you receive a response . ## Step 4. Check the result After receiving the request, Dojo creates a payment intent and returns its unique id: ```json { "id": "pi_sandbox_RBMHTJ4fIkmSppDILZVCGw", ... } ``` Use this `id` to create a link in the following format: `https://pay.dojo.tech/checkout/{id}` Follow the link to see the result. --- ## Next steps You're now ready to start building your payment integration. You can integrate with our API in several ways, for a detailed integration guide, select an option below. If you're not sure where to start, we recommend you visit the [payment intents](https://docs.dojo.tech/api#tag/Payment-intents) documentation. [![](https://docs.dojo.tech/images/dojo-icons/Star.svg) **Payment intent** The first thing any integration starts with.](manage-payments/payment-intent) [![](https://docs.dojo.tech/images/dojo-icons/ShoppingBag.svg) **Checkout Page** A prebuilt payment page for accepting payments on your website.](/payments/accept-payments/online-payments/checkout-page) [![](https://docs.dojo.tech/images/dojo-icons/Link.svg) **Payment Links** Links that you send to your customer and accept payments without a website.](/payments/accept-payments/online-payments/payment-links) [![](https://docs.dojo.tech/images/dojo-icons/Layout.svg) **Components** Our ready-made JavaScript components that you can combine with your own components.](/payments/accept-payments/online-payments/components) [![](https://docs.dojo.tech/images/dojo-icons/Copy.svg) **Sample integrations** Clone examples integrations.](https://github.com/dojo-engineering/dojo-samples) --- ## Pay at Table The **["Pay at Table"](https://support.dojo.tech/hc/en-gb/articles/360020950580-Using-Pay-at-Table)** (PAT) integration allows waiters to retrieve and pay for [orders](https://docs.dojo.tech/core-concepts/orders) on a EPOS, via Dojo card machines. This integration communicates with the EPOS system to retrieve open [orders](https://docs.dojo.tech/core-concepts/orders) and notify the EPOS system about payments via the **[EPOS Data API](https://docs.dojo.tech/api-hosting/epos-data)**. We recommend reading our documentation on [Orders](https://docs.dojo.tech/core-concepts/orders) before beginning this integration, as this is the main entity which the Pay at Table integration depends upon: the Dojo card machines will display payable orders which are returned from the EPOS system via the [SearchOrders](https://docs.dojo.tech/core-concepts/orders#search-orders) capability, lock and unlock orders via the [CreateOrderLock](https://docs.dojo.tech/core-concepts/orders#locking) and [DeleteOrderLock](https://docs.dojo.tech/core-concepts/orders#unlocking) capabilities, and provide payments to be recorded via the [RecordOrderPaymentById](https://docs.dojo.tech/core-concepts/orders#record-order-payment) capability. Dojo may also request to extend the length of the table lock by invoking the [ExtendOrderLock](https://docs.dojo.tech/core-concepts/orders#extending) capability. ## Integration You can integrate into the PAT flow using a combination of the [REST API](https://docs.dojo.tech/api-hosting/epos-data#rest), and/or the [WebSockets API](https://docs.dojo.tech/api-hosting/epos-data#websockets) implementation of the EPOS Data API, depending on your EPOS system's architecture. If you're unsure as to which implemenation option would best suit your system please contact your Partnership Development Manager (PDM). >The following **capabilities** are required to be implemented for Pay at Table: ### SearchOrders > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/paths/~1v1~1orders~1search/post > See OpenAPI spec for SearchOrdersV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-SearchOrdersV1_Request This capability enables searching for orders based on various criteria. It supports filtering and pagination to help Dojo products efficiently find orders within the POS system. Each Dojo product has different requirements on what filters must be implemented which can be found on the product documentation page(s). ### GetOrderById > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-get-orders-orderId > See OpenAPI spec for GetOrderByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-GetOrderByIdV1_Request This capability enables Dojo to retrieve detailed information about a specific order using its unique order ID. This is crucial for order tracking and status updates. ### GetOrderBillById > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-get-order-bill > See OpenAPI spec for GetOrderBillByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-GetOrderBillByIdV1_Request This capability allows the terminal to request a Bill - a printable version of the Order. The EPOS can customise the fields and layout of the Bill on a per request basis. ### RecordOrderPaymentById > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-post-record-order-payment > See OpenAPI spec for RecordOrderPaymentByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-RecordOrderPaymentByIdV1_Request This capability allows Dojo to record a payment against an order. All payments recorded this way will be sent with their `paymentIntentId` which is unique and can be used for both deduplication and to control the lifecycle of the payment with operations like Get and Reversal. ### Order-locking The following capabilities relate to an optional [order-locking flow](https://docs.dojo.tech/payments/pay-at-table/flows#createorderlock), giving the POS the opportunity to "lock" orders to prevent further changes while payment is being made, and then notifying the POS when an order is ready to be "unlocked". > **Note:** Although implementing an order-locking flow is optional, all capabilities listed below must be registered for order-locking to be supported. ### CreateOrderLock > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-post-order-lock > See OpenAPI spec for CreateOrderLockV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-CreateOrderLockV1_Request This capability allows Dojo to fetch the latest and full state of the order from the POS system. This will include a unique `lockId` and offer the POS the opportunity to "lock" the table to prevent further changes while payment is being made, although this is not mandatory. ### DeleteOrderLock > See OpenAPI spec for DELETE endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-delete-order-lock > See OpenAPI spec for DeleteOrderLockV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-DeleteOrderLockV1_Request This capability, when requested, gives the opportunity for the POS to allow further actions and updates to the order if these were previously disabled by a CreateOrderLock. ### ExtendOrderLock > See OpenAPI spec for PUT endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-put-extend-order-lock > See OpenAPI spec for ExtendOrderLockV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-ExtendOrderLockV1_Request This capability allows Dojo to extend the length of a requested Order lock if required by the card machine. With this implemented Dojo will request locks with shorter expiries and extend them when needed, this reduces the chance of a lock being held on an order for a long period of time when there is a communication breakdown between Dojo and the POS. --- ## Printable Bills > **Info:** The capabilities mentioned on this page must be registered with the **EPOS Capabilities API** prior to initiating a Pay At Table flow, > learn more [here](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities). ## Capability ### GetOrderBillById > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-get-order-bill > See OpenAPI spec for GetOrderBillByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-GetOrderBillByIdV1_Request This capability allows the terminal to request a Bill - a printable version of the Order. The EPOS can customise the fields and layout of the Bill on a per request basis. ## Overview If the GetOrderBillById capability has been set for an account, at anytime during the Pay at Table flow, the payment device can request a "printable bill" - a nicely formatted view of an Order, designed to be shown to the merchant, physcially or digitally. Implementing this feature will improve the payment flow for merchants and customers, allowing them to give out itemised bills, with logos, websites, QR codes etc without needing to walk back to the EPOS each time. ## Full Example
```json { "header": { "lines": [ { "logo": { "svgImage": "" }, "lineType": "Logo" }, { "merchantName": { "name": "Dojo" }, "lineType": "MerchantName" }, { "merchantAddress": { "addressLines": [ "Brunel Building", "1 & 2 Canalside Walk" ], "postcode": "London W2 1DG" }, "lineType": "MerchantAddress" }, { "text": { "value": "Welcome to Our Store!", "size": "Header1", "align": "Center", "emphasisBold": true }, "lineType": "Text" }, { "image": { "svgImage": "...", "align": "Left" }, "lineType": "Image" }, { "horizontalLine": { "line": "Single" }, "lineType": "HorizontalLine" }, { "text": { "value": "Table 5", "size": "Header2", "align": "Left" }, "lineType": "Text" }, { "text": { "value": "Becky 15/03/2022 20:08", "size": "Body", "align": "Center" }, "lineType": "Text" }, { "text": { "value": "Transaction:6328", "size": "Body", "align": "Right" }, "lineType": "Text" } ] }, "order": { "id": "ord_12345678", "details": { "orderType": "DineIn", "dineIn": { "tableId": "Table 5", "waiterId": "Becky" } }, "items": [ { "quantity": 2, "name": "Pizza Pepperoni", "plu": "1234", "amountPerItem": { "value": 1235, "currencyCode": "GBP" } }, { "quantity": 2, "name": "Lager", "plu": "1245", "amountPerItem": { "value": 510, "currencyCode": "GBP" } }, { "quantity": 1, "name": "Water Still", "plu": "1", "amountPerItem": { "value": 50, "currencyCode": "GBP" } }, { "quantity": 2, "name": "Coca Cola", "plu": "2", "amountPerItem": { "value": 249, "currencyCode": "GBP" } }, { "quantity": 1, "name": "Burger", "plu": "234", "amountPerItem": { "value": 1090, "currencyCode": "GBP" }, "modifiers": [ { "name": "No Lettuce", "quantity": 1, "amountPerItem": { "value": 0, "currencyCode": "GBP" }, "plu": "74983" } ] }, { "quantity": 1, "name": "Burger", "plu": "234", "amountPerItem": { "value": 1090, "currencyCode": "GBP" }, "modifiers": [ { "name": "Extra Cheese", "quantity": 1, "amountPerItem": { "value": 0, "currencyCode": "GBP" }, "plu": "10987" }, { "name": "Bacon", "quantity": 1, "amountPerItem": { "value": 0, "currencyCode": "GBP" }, "plu": "872" } ] } ], "discounts": [ { "name": "10% discount", "amountTotal": { "value": 6.21, "currencyCode": "GBP" }, "amountPercentage": 1000 } ], "serviceChargeAmount": { "value": 62.95, "currencyCode": "GBP" }, "taxLines": [ { "id": "VAT", "name": "VAT", "amountPercentage": 20, "amountTotal": { "value": 62.95, "currencyCode": "GBP" } } ], "status": "Finalized", "createdAt": "2022-03-15T20:00:00Z", "updatedAt": "2022-03-15T20:05:00Z", "totalAmount": { "value": 6295, "currencyCode": "GBP" }, "payable": true, "paidAmount": { "value": 0, "currencyCode": "GBP" }, "reference": "Table 5" }, "footer": { "lines": [ { "text": { "value": "Thank you", "size": "Header1", "align": "Center" }, "lineType": "Text" }, { "taxNumber": { "name": "VAT", "number": "342 6287 32" }, "lineType": "TaxNumber" }, { "url": { "url": "https://www.website.com", "showQR": true, "showURL": true }, "lineType": "URL" } ] } } ```
## Bill Sections There are several pre-defined bill sections defined in this API, simplifying the design and layout of bills. However if more control is desired, there are more flexible sections that give complete freedom to the EPOS to dictate the design and layout. The `Header` and `Footer` elements in bill wrap the `Order`, which is the same object returned in the [Get Order by ID](https://docs.dojo.tech/core-concepts/orders#get-order-by-id) request. The `Header` and `Footer` are both arrays of `Lines`. In a line ensure you specify the `lineType` and populate the corresponding field in that object. Some examples are below. ### Predefined Sections #### Logo and Image The `Logo` and `Image` line types are similar, both taking an SVG. However a `Logo` will always appear at the top of the bill, whereas an `Image` will be in the order it is defined in, and allows for `Left`, `Right` or `Center` alignment. In the example below the Logo would be placed at the top, and the Image would be left aligned. ```json { "logo": { "svgImage": "" }, "lineType": "Logo" } ``` ```json { "image": { "svgImage": "" "align": "AlignLeft" }, "lineType": "Image" } ``` #### Merchant information We provide predefined fields for merchant information: - `MerchantEmailAddress` - `MerchantName` - `MerchantPhoneNumber` - `MerchantAddress` These will all be preformatted and simply require the fields to be populated. #### URL The `URL` object allows a website to be displayed in multiple forms. Set the `URL` and optionally a description for extra text and then decide if it should be displayed as a QR code (which we will generate) or printed URL. This allows you to link out to surveys, loyalty schemes or a website. For example, this would display this website as a QR code and a description. ```json { "url": { "url": "https://example.com/", "description": "Visit our website!", "showQR": true, "showURL": false }, "lineType": "URL" } ``` #### Tax We allow a tax number to be displayed, however you must set the name of the tax too. It is your responsibility to ensure the bill is a valid tax receipt for the market you're operating in. ```json { "taxNumber": { "name": "VAT", "number": "12345678" }, "lineType": "TaxNumber" } ``` #### Horizontal Lines A horizonal line can be used to create a divider across the width of the bill. There are `Single` and `Double` lines. ### Custom Sections #### Free Text This field allows text to be input, customising the size, weight and alignment. For example, this will be displayed as the largest text size, and aligned in the center. ```json { "text": { "value": "Thank you for your business!", "size": "Header1", "align": "Center" }, "lineType": "Text" } ``` --- ## Flows(Pay-at-table) > **Info:** The capabilities mentioned on this page must be registered with the **EPOS Capabilities API** prior to initiating a Pay At Table flow, > learn more [here](https://docs.dojo.tech/api-hosting/epos-data#registering-capabilities). The following diagram demonstrates how the Pay at Table product will interact with Dojo and the POS system for settling a table when initiated by a **Dojo product**, such as a **Dojo card terminal** or **QR Pay**: ![](https://docs.dojo.tech/images/pat/flow-diagrams/pat-flow-diagram2.jpg) **Flow diagram: Pat Flow Diagram2** ```mermaid sequenceDiagram participant DP as Dojo Product participant B as Dojo Backend participant P as POS DP->>B: List orders B->>P: SearchOrders P-->>B: SearchOrders response DP->>B: Get a specific order to pay B->>P: GetOrderById P-->>B: GetOrderById response DP->>B: Takes payment B->>P: Record Payment Request P-->>B: Record Payment Response ``` The following diagram demonstrates how the Pay at Table product will interact with Dojo and the POS system for settling a table when initiated by a **Dojo card terminal**, and when order locking is enforced by the POS during the payment flow. ![](https://docs.dojo.tech/images/pat/flow-diagrams/pat-flow-diagram1.jpg) **Flow diagram: Pat Flow Diagram1** ```mermaid sequenceDiagram participant T as Dojo Go Terminal participant B as Dojo Backend participant P as POS T->>B: List orders B->>P: SearchOrders P-->>B: SearchOrders response T->>B: Get a specific order to pay B->>P: GetOrderById* P-->>B: GetOrderById response B->>P: Lock an EPOS Order P-->>B: Lock an EPOS Order response T->>B: Takes payment B->>P: Record Payment Request** P-->>B: Record Payment response B->>P: Unlock an EPOS Order P-->>B: Unlock an EPOS Order response Note over T,P: *GetOrderById may be called during flow by certain products, or to print an EPOS bill. Note over T,P: **Multiple Record Payment requests may occur, such as in the instance where a bill is split between several payees. ``` **Note**: Support of the "no locking flow" detailed above is considered mandatory, while support of the "Locking flow" is only considered mandatory if the [CreateOrderLock](https://docs.dojo.tech/core-concepts/orders#locking), [ExtendOrderLock](https://docs.dojo.tech/core-concepts/orders#extending) and [DeleteOrderLock](https://docs.dojo.tech/core-concepts/orders#deleting) capabilities are registered. If these capabilities are registered, the POS is expected to restrict order access and changes while an order lock is requested. ## Step 1: List orders via SearchOrders > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/paths/~1v1~1orders~1search/post > See OpenAPI spec for SearchOrdersV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-SearchOrdersV1_Request **Main page**: [Orders](https://docs.dojo.tech/core-concepts/orders#search-orders) The initial step in the Pay at Table flow involes the waiter opening the "Integration" screen on the payment device, if configured (on the device) the waiter will be asked to input their waiter id which will be included in the SearchOrders request to the POS system. If the user is a customer and initiating via another product, such as **QR to Pay**, the request will include a `tableId` field to filter the orders by. When initiated from a Dojo card machine, the orders returned via the [SearchOrders](https://docs.dojo.tech/core-concepts/orders#search-orders) request are then presented on the payment device in a list for the waiter to select from, the name presented on the device for each order is determined by the following logic (first condition to match): - `displayName` field if populated in the Order - `tableId` field if populated in the Order - The mandatory `id` field of the Order - Otherwise the `id` field of an Order is used **Exceptions** - In cases where the names of orders to be presented on the payment device have duplicates a suffix of `"- $number"` will be added to the name e.g. `Table1 - 1`. - Dojo payment devices have a 24-character limit for order names. Names longer than this limit will be truncated. **Note:** We will only request payable orders, by setting the `payableOnly` parameter to `true`. Therefore only orders which can be paid for will be presented on the payment device, allowing some orders to be hidden if they're being edited on the POS or have already been fully paid off. ## Step 2: Get a specific order to pay via or GetOrderById or CreateOrderLock **Main page**: [Orders](https://docs.dojo.tech/core-concepts/orders) The next step in the Pay at Table flow is triggered when a user selects an Order. This may materialise as either: ### GetOrderById > See OpenAPI spec for GET endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-get-orders-orderId > See OpenAPI spec for GetOrderByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-GetOrderByIdV1_Request - A waiter choosing from the list of orders (from the previous step) or a customer selecting via the **QR to Pay** flow, which will trigger a [GetOrderById](https://docs.dojo.tech/core-concepts/orders#get-order-by-id) to retrieve an up-to-date representation of the order details. This step ensures that the most recent version of the order is presented on the payment screen before any payment is taken. ### CreateOrderLock > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-post-order-lock > See OpenAPI spec for CreateOrderLockV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-CreateOrderLockV1_Request - A waiter choosing from the list of orders (from the previous step), which will trigger a CreateOrderLock (which includes their `waiterId` if given) to fetch the latest and full state of the order from the POS system using the `id` field. This will include a unique `lockId` and expects the POS to "lock" the table to prevent further changes while payment is being made. **Note**: Both methods of retrieving order data may be invoked during the same flow, such as in the instance where an order is locked and then GetOrderById is used to retrieve a POS receipt for printing, so if the POS is enforcing order locking it must still accept and respond to GetOrderById requests. ## Step 3: Takes payment, payment event sent via Record Payment request > See OpenAPI spec for POST endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-post-record-order-payment > See OpenAPI spec for RecordOrderPaymentByIdV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-RecordOrderPaymentByIdV1_Request **Main page**: [Record Payments](https://docs.dojo.tech/core-concepts/orders#record-order-payment) The waiter can now take the payments for this order, and depending on how the customer chooses to pay, there may be a single payment or multiple for the order (split payment or pay by items). As part of the payment process, a RecordOrderPaymentById will be sent to the POS for each individual payment, this will include the `orderId` as well as other information such as the `paymentIntentId` - this ID should be recorded by the POS to facilitate payment tracking and refunds. If a waiter ID was provided on the payment device, an entry with the key `waiterId` will be included in the `metadata` on those created [payment intents](https://docs.dojo.tech/payments/manage-payments/payment-intent). The POS should respond to this request with a 200 response to indicate that the payment has been acknowledged and recorded. The POS should also respond with the current order "status" to show any changes that may have occurred to this attribute. If the payment cannot be recorded, such as in the event of a mismatching value being submitted in the RecordOrderPaymentById request, the POS should reject the request with a `409` error and the relevant `errorType`, in most cases this will be `Conflict`. This will trigger a payment reversal on the payment device or customer app and prompt the user to reattempt the payment. **Note:** If the order is initiated via a Dojo product such as **QR to Pay** then this may be the final step in the payment flow. **Tracking Payment Intents through Events** As an additional measure, the POS can also track the status of Payment Intents by subscribing to the `payment_intent.status_updated` via [Webhook](https://docs.dojo.tech/development-resources/webhooks#payment-intents-webhooks) if using REST, or by registering the [HandleEvent:payment_intent.status_updated](https://docs.dojo.tech/core-concepts/dojo-events#handle-event-payment-intent-status-updated) capability if using Websockets. In order to get the full information for a payment after receiving a RecordOrderPaymentById, the POS system can [lookup the payment intent via the Dojo API](https://docs.dojo.tech/api#tag/Payment-intents/operation/PaymentIntents_Get): this can be useful when retrieving receipt data, for example. To determine which order on the POS system a [payment intent](https://docs.dojo.tech/payments/manage-payments/payment-intent) belongs to, the POS system should look at the `orderDetails.externalId` field on the [payment intent](https://docs.dojo.tech/payments/manage-payments/payment-intent). This field will be set to the `id` field from the order returned by the POS in the previous steps. **Note:** Events are delivered with an **At least once** guarantee, so the POS will need to handle receiving duplicate events for the same [payment intent](https://docs.dojo.tech/payments/manage-payments/payment-intent). ## Step 4: Order is unlocked > See OpenAPI spec for DELETE endpoint details: https://docs.dojo.tech/epos-data/api#tag/Orders/operation/v1-post-order-lock > See OpenAPI spec for DeleteOrderLockV1 endpoint details: https://docs.dojo.tech/epos-data/ws/api#spec-operation-receive-DeleteOrderLockV1_Request **Main page**: [Orders](https://docs.dojo.tech/core-concepts/orders#unlocking) If order locking is enforced, then the final step of the Pay at Table flow is for the order to be unlocked: Dojo will request this by sending a DeleteOrderLock containing the relevant `orderId` and `lockId`. This request expects the POS to allow further actions and updates to the order if it remains open. --- ## Go-live checklist(Pay-at-table) Dojo is committed to providing the best possible experience for our mutual customers. To achieve this, we require that all integrations meet our minimum requirements. As part of this process, our team will conduct UAT testing with you before accrediting your solution to be used with our customers. To facilitate a smooth onboarding experience with our Pay-at-Table integration, Dojo has prepared a comprehensive testing checklist. Please use this checklist as a reference for self-accreditation before Dojo performs UAT. If you're ready to begin UAT testing with us, or require development support, you can reach out to our team using the links at the bottom of this page. Configuration These tests relate to the configuration of the integration on your POS. | Scenario | Steps to Reproduce | Expected Outcome | |-------|-----|----| | Incorrect authorization credentials. | Input an invalid API Key, then attempt to establish a connection with the EPOS Data API. | The POS should display an appropriate error message and / or status code indication authorization was unsuccessful. | |API Version used.| Record the version of the API developed against, this should be hard-coded. | Version header is not able to be manipulated on the POS.| |Minimum version of POS support.| Record the minimum version of the POS that supports the integration.| This must be shared with Dojo during the accreditation process| |Implementation.| Record whether or not you are using our REST, Websocket or a mixture of both interfaces.| This will be recorded by Dojo during the accreditation process.| Registering Capabilities In the Dojo EPOS Data API, [capabilities](https://docs.dojo.tech/api#tag/Capabilities/paths/~1epos~1integrations/get) represent specific actions that the POS system can perform. These capabilities are linked to corresponding API endpoints in the POS system. By defining these capabilities, the POS system communicates to Dojo which features are supported and accessible. | Scenario | Steps to Reproduce | Expected Outcome | |------------|------|---------------------------| | Get all registered capabilities | The POS should have the ability to retrieve all currently registered capabilities | The registered capabilities do not need to be displayed to the user, but should be accessible if needed. This can be used to confirm that the correct capabilities are registered for Pay-At-Table. | | Register a new capability. | All capabilities needed for the integration should be registered. | Capabilities should be based on what a specific customer can support, therefore the POS should be able to support all endpoints for every customer, or register specific capabilities based on requirement. | Orders These tests cover [Orders](https://docs.dojo.tech/core-concepts/orders). The Order entity represents the core component of the Ordering API, containing all relevant information about an order placed by customers at a given location. An order can consist of multiple items, each with details like status, quantity, price, and applied modifiers. If [order locking capabilities](https://docs.dojo.tech/core-concepts/orders#locking) are registered, the POS must be able to respond to payment flows initiated by both `GetOrderById` and `CreateOrderLock` requests. | Scenario | Steps to reproduce | Expected outcome | |----------|-------|---------| | [SearchOrders](https://docs.dojo.tech/core-concepts/orders#search-orders) request with `payableOnly` set to true.| Using the Epos tester tool or the Dojo card machine, initiate a `SearchOrders` request. | The POS should only return tables that are available to be paid. | | GetOrderById. | Using the Epos tester tool or the Dojo card machine, initiate a `GetOrderById` request by selecting an order to pay from the Order list. | The POS should return information about the specific order requested. | | Water ID Validation. | Using a Dojo Card machine, initiate a `SearchOrders` request while entering a waiter ID. | Dojo will record whether or not the POS validates the `waiterId` field and only returns tables available to that waiter. | | `Status` is returned as required.| Using the Epos tester tool or the Dojo card machine, initiate a `SearchOrders` request. | Not all statuses are required to be supported, but a status must be returned in the response for `SearchOrders`. Dojo will record the statuses that are supported by the POS. | | `ItemLines` are supported. | Using the Epos tester tool or the Dojo card machine, initialize a search orders request. Initiate a `GetOrderById` by using the "Print Bill" function to print the POS bill. | ItemLines should be returned in the correct format. This is a pre-requisite to be able to print POS bills from the card machine. | | Order Locking is implemented. | When registered as a capability, initiate a `CreateOrderLock` request by selecting an order using the Dojo Card Machine and pay off the bill; initiate a `DeleteOrderLock` by completing or exiting out of the payment flow. | If supported, the POS should lock the order when requested, preventing further manipulation to the order items or status, and unlock when requested. | Record a Payment These tests cover the [RecordOrderPaymentById](https://docs.dojo.tech/core-concepts/orders#record-order-payment) capability and the different variations of how a guest may choose to pay. | Scenario | Steps to reproduce | Expected outcome | |----------|-------|---------| |Successful payment in full.| Using a Dojo card machine, pay an order in full without splitting the bill. | The POS should record the payment, including its `paymentIntentId`, against the order. | |Payment in full with split bill.| Using a Dojo card machine, pay an order in full by choosing either of the split options and splitting the bill by at least 2 payments. | The POS should record each payment, including its `paymentIntentId`, against the order. | |Payment in full with split bill and Gratuity.| Using a Dojo card machine, pay an order in full by choosing either of the split options and splitting the bill by at least 2 payments; add gratuity to at least one of the payments. | The POS should record each payment, including its `paymentIntentId` and `tipsAmount.value`, against the order. | |Partial Payment with and without gratuity.| Using a Dojo card machine, pay an order by choosing either of the split options and split by at least 2 ways; add gratuity to the first payment; after completing the first payment, exit out of the payment flow by selecting cancel. | The POS should record the payment, including its `paymentIntentId` and `tipsAmount.value`, against the order; the order should then return to a `payable` state and the outstanding balance should reflect the payment(s) taken. | Refunds These tests cover Refunds. Any payments taken via the Epos Data API can be refunded without the cardholder present through the [Dojo API](https://docs.dojo.tech/api)'s [Matched Refund](https://docs.dojo.tech/api#tag/Terminal-sessions/operation/TerminalSession_Create) function. | Scenario | Steps to reproduce | Expected outcome | |----------|-------|---------| |Successful Matched Refund.| Create a terminal session via the Dojo API with a session type of matched refund. | The POS should be able to initiate a Matched Refund and call the Payment Intent endpoint to confirm the refund was successful. | |Unsuccessful Matched Refund.| The POS should store the paymentIntent ID against the orderId, so they can make use of integrated centralized refunds. | In case of the refund not being successful, the POS should display an appropriate error to the user. | Error Handling These tests cover some of the possible ways in which errors can occur and aim to create additional resilience. | Scenario | Steps to reproduce | Expected outcome | |----------|-------|---------| | Websocket disconnection handling. | If the API is hosted by Websocket, the POS should periodically check the connection status of the maintained Websocket to guard against network related incidents. | If the socket disconnects the connection should be re-established as soon as possible. | | GetOrderById - none existent ID. | Using the Epos tester tool, Initiate a `GetOrderById` with an ID that does not exist. | The POS should return an appropriate error to the request. | [![](https://docs.dojo.tech/images/dojo-icons/Headset.svg) **Support** Our Partner Enablement team is always happy to help with any questions you have.](mailto:partnertech@dojo.tech) [![](https://docs.dojo.tech/images/dojo-icons/Message.svg) **Stack Overflow** Find answers to practical questions.](https://stackoverflow.com/tags/dojo.tech) --- ## Choosing your online payments integration >Take our short survey to get a recommendation based on your needs. ## Do you want to accept payments on a web app or mobile app? [**← Back**](https://docs.dojo.tech/payments/) [![](https://docs.dojo.tech/images/dojo-icons/Browsers.svg) **Web App** I want to accept payments on a web app.](question-1) [![](https://docs.dojo.tech/images/dojo-icons/Mobile.svg) **Mobile App** I want to accept payments on a mobile app.](result-mobile-ios) --- ## Choosing your online payments integration(Survey) >Take our short survey to get a recommendation based on your needs. ## Do you plan to accept payments on Android or iOS? [**← Back to previous question**](https://docs.dojo.tech/payments/survey/mobile-question-1) [![](https://docs.dojo.tech/images/dojo-icons/AppleLogo.svg) **iOS** I want to accept payments on an iOS app.](result-mobile-ios) [![](https://docs.dojo.tech/images/dojo-icons/AndroidLogo.svg) **Android** I want to accept payments on an Android app.](result-mobile-android) --- ## Choosing your online payments integration(3) >Take our short survey to get a recommendation based on your needs. ## Do you have your own website or app? [**← Back to previous question**](https://docs.dojo.tech/payments/survey/mobile-question-1) [![](https://docs.dojo.tech/images/dojo-icons/TickCircle.svg) **Yes** I have a website or an app.](question-2) [![](https://docs.dojo.tech/images/dojo-icons/DeleteCircle.svg) **No** I don't have a website or an app.](result-payment-link) --- ## Choosing your online payments integration(4) >Take our short survey to get a recommendation based on your needs. ## Do you plan to use an e-commerce platform? [**← Back to previous question**](https://docs.dojo.tech/payments/survey/question-1) [![](https://docs.dojo.tech/images/dojo-icons/TickCircle.svg) **Yes** I plan to use an e-commerce platform (for example, Magento, OpenCart, WooCommerce).](result-plugins) [![](https://docs.dojo.tech/images/dojo-icons/DeleteCircle.svg) **No** I don't plan to use an e-commerce platform.](question-3) --- ## Choosing your online payments integration(5) >Take our short survey to get a recommendation based on your needs. ## Do you want to have a customizable UI? [**← Back to previous question**](https://docs.dojo.tech/payments/survey/question-2) [![](https://docs.dojo.tech/images/dojo-icons/TickCircle.svg) **Yes** I need a customizable UI.](result-components) [![](https://docs.dojo.tech/images/dojo-icons/DeleteCircle.svg) **No** Having a prebuilt UI is fine for me.](result-checkout) --- ## Our recommendation [**← Start again**](https://docs.dojo.tech/payments/survey/mobile-question-1) ## Dojo Prebuilt Checkout Page Based on your answers we recommend you to use Dojo Prebuilt Checkout Page. Dojo Prebuilt Checkout Page is a prebuilt UI page where you send your customers to finalize their payment details. [![](https://docs.dojo.tech/images/dojo-icons/BookBookmark.svg) **Step-by-step guide** Learn how to implement Dojo Prebuilt Checkout Page to accept payments.](../accept-payments/online-payments/checkout-page/step-by-step-guide) --- ## Our recommendation(Survey) [**← Start again**](https://docs.dojo.tech/payments/survey/mobile-question-1) ## Dojo Components Based on your answers we recommend you to use Dojo Components. Dojo Components are our ready-made JavaScript components that you can add to your website to accept payments. The components have error handling and input validation on the Client-side. [![](https://docs.dojo.tech/images/dojo-icons/PaymentCard.svg) **Card Component** Learn how to use our card component to accept payments.](/payments/accept-payments/online-payments/components/card) [![](https://docs.dojo.tech/images/dojo-icons/Wallet.svg) **Wallet Component** Learn how to use our single component for Apple Pay and Google Pay.](/payments/accept-payments/online-payments/components/wallet) --- ## Our recommendation(3) [**← Start again**](https://docs.dojo.tech/payments/survey/mobile-question-1) ## Android SDK Based on your answers, we recommend you to integrate Dojo's Android SDK into your app. You can then accept payments from customers who use Android devices. When a customer tries to shop on your app and initiates a payment, the customer will be redirected to a Dojo prebuilt checkout page to complete the payment. You can also customize this payment page. [![](https://docs.dojo.tech/images/dojo-icons/AppleLogo.svg) **Android SDK** Start creating a checkout page in your Android application.](../../mobile-integration/android/accept-payments/android-step-by-step-guide) --- ## Our recommendation(4) [**← Start again**](https://docs.dojo.tech/payments/survey/mobile-question-1) ## iOS SDK Based on your answers, we recommend you to integrate Dojo's iOS SDK into your app. You can then accept payments from customers who use iOS devices. When a customer tries to shop on your app and initiates a payment, the customer will be redirected to a Dojo prebuilt checkout page to complete the payment. You can also customize this payment page. [![](https://docs.dojo.tech/images/dojo-icons/AppleLogo.svg) **iOS SDK** Start creating a checkout page in your iOS application.](../../mobile-integration/ios/accept-payments/ios-step-by-step-guide) --- ## Our recommendation(5) [**← Start again**](https://docs.dojo.tech/payments/survey/mobile-question-1) ## Payment Link Based on your answers we recommend you to use Payment Link. It's a link you can send to your customer, and it will take them to a Dojo Prebuilt Checkout Page for them to complete the payment. The payment page works across different devices and can be customized. With the payment links, you can sell online without a website. You could send the payment links after interacting with your customer through chat or email, or any other channel. You can create payment links either in the Dojo App, or using the Dojo API: [![](https://docs.dojo.tech/images/dojo-icons/MobileInformation.svg) **Dojo App** Create each payment link manually using Dojo App.](https://support.dojo.tech/hc/en-gb/articles/4415821097874-How-to-use-payment-links) [![](https://docs.dojo.tech/images/dojo-icons/BookBookmark.svg) **API step-by-step guide** Generate payment links automatically through the API.](/payments/accept-payments/online-payments/payment-links/step-by-step-guide) --- ## Our recommendation(6) [**← Start again**](https://docs.dojo.tech/payments/survey/question-1) ## Plugins Based on your answers, you're already using an e-commerce platform. Because of this, we recommend you to use plugins to accept payments through Dojo. Try one of the plugins officially developed and maintained by our team: