# Dojo Payment Intents Documentation > Guides for managing payment intents, setup intents, captures, refunds, cancellations, saved cards, and tokenization. These concepts are shared across online and in-person payment flows. API quick reference: - **API base URL**: https://api.dojo.tech - **Environment selection**: Sandbox and production both use `https://api.dojo.tech`; the API key determines which environment receives the request - **Authentication**: `Authorization: Basic ` (literal `Basic ` prefix; do not base64-encode `api_key:`) - **Version header**: `version: 2026-02-27` Use this file as the shared payment lifecycle reference for online, terminal, and table-based integrations. Machine-readable specs: - [Dojo API v3](https://docs.dojo.tech/api/v3/bundled.json) For complete integration, also load: - `llms-online.txt` — hosted checkout, components, payment links, and virtual terminal flows - `llms-inperson-pac.txt` — terminal session orchestration for Pay at Counter - `llms-inperson-pat.txt` — table-session flows and EPOS coordination for Pay at Table This file contains all documentation content in a single document following the llmstxt.org standard. ## 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/development-resources/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/development-resources/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. --- ## 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/development-resources/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/development-resources/llm-friendly-docs#sandbox-and-production-environments) and a secret key for the [production environment](https://docs.dojo.tech/development-resources/llm-friendly-docs#sandbox-and-production-environments). You can find your keys in the Developer Portal. Learn how to [manage your API keys](https://docs.dojo.tech/development-resources/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/development-resources/api-keys) in the Developer Portal. > > If your company account has different [location accounts](https://docs.dojo.tech/development-resources/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/development-resources/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) > > > > --- > > ## 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/development-resources/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/development-resources/portal#webhooks). To start using webhooks, you need: 1. [Choose which events to subscribe to](https://docs.dojo.tech/development-resources/webhooks#step-1-choose-which-events-to-subscribe-to). 2. [Enable the webhook using the webhook endpoint](https://docs.dojo.tech/development-resources/webhooks#step-2-enable-the-webhook). 3. [Verify Dojo webhooks](https://docs.dojo.tech/development-resources/webhooks#step-3-verify-dojo-webhooks). 4. [Go live](https://docs.dojo.tech/development-resources/webhooks#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/development-resources/webhooks#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/development-resources/webhooks#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). --- ## 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/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/development-resources/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/development-resources/cancelling-payments/refund) or [reversed](https://docs.dojo.tech/development-resources/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/development-resources/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/development-resources/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/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/development-resources/webhooks#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 > 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/development-resources/webhooks#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/development-resources/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/development-resources/webhooks#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/development-resources/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/development-resources/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/development-resources/webhooks#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.