# Payment instruments You can store a customer's card or bank account details as a payment instrument to reuse in future payments or payouts. - [Create a card payment instrument](https://www.checkout.com/docs/payments/store-payment-details/payment-instruments.md#Create_a_card_payment_instrument). - [Create a bank account payment instrument](https://www.checkout.com/docs/payments/store-payment-details/payment-instruments.md#Create_a_bank_account_payment_instrument). You can also [store your own metadata](#Store_metadata_with_an_instrument) with a payment instrument. --- ## Create a card payment instrument You can store card details as a payment instrument using the following APIs: - Payments API – To make a payment with a card token or full card details, or verify a card - Instruments API – To convert a card token into a payment instrument > **Information** > > We recommend using the Payments API if you process payments with Checkout.com, because we check that the card is valid before storing it. With both APIs, you can create an instrument for a new customer, or an existing one. If you provide: - A new email in the `customer` object – We create a new customer and link them to the instrument. - An existing customer ID or email – We link the instrument to the existing customer. ### Using the Payments API Call the [Request a payment or payout](https://api-reference.checkout.com/tag/Payments/#operation/requestAPaymentOrPayout) endpoint: > **Information** > > Your base URL's `{prefix}` value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see [API endpoints](https://www.checkout.com/docs/developer-resources/api/api-endpoints.md). **Production** `POST` `https://{prefix}.api.checkout.com/payments` **Sandbox** `POST` `https://{prefix}.api.sandbox.checkout.com/payments` ### Request example The following example includes the ID of an existing customer, who is then linked to the payment instrument. ```json { "source": { "type": "token", "token": "tok_4gzeau5o2uqubbk6fufs3m7p54" }, "amount": 6500, "currency": "USD", "customer": { "customer.id": "cus_udst2tfldj6upmye2reztkmm4i" } } ``` ### Response example If successful, you receive a `201` response that includes the payment instrument ID in the `source.id` field, prefixed with `src_`. You can use this in future payment requests. It also includes the linked customer's ID in the `customer.id` field, prefixed with `cus_`. **201 Success** ```json { "id": "pay_mbabizu24mvu3mela5njyhpit4", "action_id": "act_mbabizu24mvu3mela5njyhpit4", "amount": 6500, "currency": "USD", "approved": true, "status": "Authorized", "auth_code": "770687", "eci": "05", "scheme_id": "638284745624527", "response_code": "10000", "response_summary": "Approved", "risk": { "flagged": false }, "source": { "id": "src_nwd3m4in3hkuddfpjsaevunhdy", "type": "card", "expiry_month": 9, "expiry_year": 2022, "scheme": "Visa", "last4": "4242", "fingerprint": "F31828E2BDABAE63EB694903825CDD36041CC6ED461440B81415895855502832", "bin": "424242", "card_type": "CREDIT", "card_category": "CONSUMER", "issuer": "Test Bank", "issuer_country": "US", "product_id": "A", "product_type": "Visa Traditional", "avs_check": "S", "cvv_check": "" }, "customer": { "id": "cus_udst2tfldj6upmye2reztkmm4i" }, "processed_on": "2024-01-25T11:03:36Z", "reference": "ORD-5023-4E89", "_links": { "self": { "href": "https://{prefix}.api.sandbox.checkout.com/payments/pay_mbabizu24mvu3mela5njyhpit4" }, "actions": { "href": "https://{prefix}.api.sandbox.checkout.com/payments/pay_mbabizu24mvu3mela5njyhpit4/actions" }, "capture": { "href": "https://{prefix}.api.sandbox.checkout.com/payments/pay_mbabizu24mvu3mela5njyhpit4/captures" }, "void": { "href": "https://{prefix}.api.sandbox.checkout.com/payments/pay_mbabizu24mvu3mela5njyhpit4/voids" } } } ``` **422 Unprocessable Content** ```json { "request_id": "0HL80RJLS76I7", "error_type": "request_invalid", "error_codes": ["payment_source_required"] } ``` ### Using the Instruments API Call the [Create an instrument](https://api-reference.checkout.com/tag/Instruments/#operation/createAnInstrument) endpoint: > **Note** > > This endpoint does not check that the card is valid before storing it. > **Information** > > Your base URL's `{prefix}` value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see [API endpoints](https://www.checkout.com/docs/developer-resources/api/api-endpoints.md). **Production** `POST` `https://{prefix}.api.checkout.com/instruments` **Sandbox** `POST` `https://{prefix}.api.sandbox.checkout.com/instruments` ### Request example This example provides a new customer `email` and `name`. This creates a new customer and the payment instrument automatically becomes their default instrument. ```json { "type": "token", "token": "tok_asoto22g2fsu7prwomy12sgfsa", "account_holder": { "billing_address": { "address_line1": "123 Anywhere St.", "address_line2": "Apt. 456", "city": "Anytown", "state": "AL", "zip": "123456", "country": "US" }, "phone": { "country_code": "+1", "number": "5551234567" } }, "customer": { "email": "john.smith@example.com", "name": "John Smith" } } ``` ### Response example If successful, you receive a `201` response that includes the instrument `id`, prefixed with `src_`. You can use this in future payment requests. It also returns the details of the linked customer. **201 Success** ```json { "id": "src_wmlfc3zyhqzehihu7giusaaawu", "type": "card", "fingerprint": "string", "expiry_month": 6, "expiry_year": 2025, "scheme": "VISA", "last4": "9996", "bin": "454347", "card_type": "CREDIT", "card_category": "CONSUMER", "issuer": "Test Bank", "issuer_country": "US", "product_id": "F", "product_type": "CLASSIC", "customer": { "id": "cus_y3oqhf46pyzuxjbcn2giaqnb44", "email": "john.smith@example.com", "name": "John Smith" } } ``` **422 Unprocessable Content** ```json { "request_id": "0HL80RJLS76I7", "error_type": "request_invalid", "error_codes": ["payment_source_required"] } ``` --- ## Create a bank account payment instrument ### Get bank account field formatting Before creating a bank account payment instrument, call the [Get bank account field formatting](https://api-reference.checkout.com/tag/Instruments/#operation/getBankAccountFields) endpoint to check the required fields for the account's country and currency. Alternatively, see [Payout formatting](https://www.checkout.com/docs/payments/request-payouts/bank-payouts/payout-formatting.md). ### Create the instrument Call the [Create an instrument](https://api-reference.checkout.com/tag/Instruments/#operation/createAnInstrument) endpoint to convert the bank account details into a bank account payment instrument. > **Information** > > Your base URL's `{prefix}` value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see [API endpoints](https://www.checkout.com/docs/developer-resources/api/api-endpoints.md). **Production** `POST` `https://{prefix}.api.checkout.com/instruments` **Sandbox** `POST` `https://{prefix}.api.sandbox.checkout.com/instruments` ### Request example ```json { "type": "bank_account", "account_type": "savings", "account_number": "13654567455", "bank_code": "123-456", "branch_code": "6443", "iban": "HU93116000060000000012345676", "bban": "3704 0044 0532 0130 00", "swift_bic": "37040044", "currency": "GBP", "country": "GB", "account_holder": { "type": "individual", "first_name": "John", "last_name": "Smith", "company_name": "Acme Corporation", "tax_id": "123456", "date_of_birth": "1986-01-01", "country_of_birth": "GB", "residential_status": "resident", "billing_address": { "address_line1": "123 High St.", "address_line2": "Flat 456", "city": "London", "zip": "SW1A 1AA", "country": "GB" }, "phone": { "country_code": "+44", "number": "1234 567890" }, "identification": { "type": "passport", "number": "09876", "issuing_country": "US" }, "email": "john.smith@example.com" }, "bank": { "name": "Test Bank", "branch": "Main branch", "address": { "address_line1": "Example Place", "address_line2": "Example Square", "city": "London", "zip": "EC2M 4XY", "country": "GB" } }, "customer": { "id": "cus_y3oqhf46pyzuxjbcn2giaqnb44", "email": "jane.smith@example.com", "name": "Jane Smith" } } ``` ### Response example If successful, the response returns the bank account payment instrument `id`, prefixed with `src_`. You can use this for [Bank Payout requests](https://www.checkout.com/docs/payments/request-payouts/bank-payouts.md). The response also returns a `fingerprint`, which is a unique token that identifies the instrument across all customers. **201 Success** ```json { "type": "bank_account", "fingerprint": "vnsdrvikkvre3dtrjjvlm5du4q", "customer": { "id": "cus_y3oqhf46pyzuxjbcn2giaqnb44", "email": "jane.smith@example.com", "name": "Jane Smith" }, "id": "src_wmlfc3zyhqzehihu7giusaaawu" } ``` **422 Unprocessable Content** ```json { "request_id": "0HL80RJLS76I7", "error_type": "request_invalid", "error_codes": ["payment_source_required"] } ``` --- ## Testing To test different payment instrument scenarios, see [Testing](https://www.checkout.com/docs/developer-resources/testing.md). --- ## Get instrument details To retrieve a specific payment instrument's details, call the [Get instrument details](https://api-reference.checkout.com/tag/Instruments/#operation/getInstrumentDetails) endpoint, and provide the instrument ID as the `{id}` path parameter. > **Information** > > Your base URL's `{prefix}` value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see [API endpoints](https://www.checkout.com/docs/developer-resources/api/api-endpoints.md). **Production** `GET` `https://{prefix}.api.checkout.com/instruments/{id}` **Sandbox** `GET` `https://{prefix}.api.sandbox.checkout.com/instruments/{id}` ### Response example If successful, you receive a `200` response containing the instrument's details. **Card payment instrument** ```json { "id": "src_lmyvsjadlxxu7kqlgevt6ebkra", "type": "card", "fingerprint": "vnsdrvikkvre3dtrjjvlm5du4q", "expiry_month": 6, "expiry_year": 2025, "name": "John Smith", "scheme": "VISA", "last4": "9996", "bin": "454347", "card_type": "CREDIT", "card_category": "CONSUMER", "issuer": "Test Bank", "issuer_country": "US", "product_id": "F", "product_type": "CLASSIC", "account_holder": { "billing_address": { "address_line1": "123 High St.", "address_line2": "Flat 456", "city": "London", "zip": "SW1A 1AA", "country": "GB" }, "phone": { "country_code": "+44", "number": "1234 567890" } }, "customer": { "id": "cus_gajmdgunwwlehbctuj6a3sifpm", "email": "jane.smith@example.com", "name": "Jane Smith", "default": true } } ``` **Bank account payment instrument** ```json { "type": "bank_account", "id": "src_wmlfc3zyhqzehihu7giusaaawu", "fingerprint": "vnsdrvikkvre3dtrjjvlm5du4q", "account_type": "savings", "account_number": "13654567455", "bank_code": "123-456", "branch_code": "6443", "iban": "HU93116000060000000012345676", "bban": "3704 0044 0532 0130 00", "swift_bic": "37040044", "currency": "GBP", "country": "GB", "account_holder": { "type": "individual", "first_name": "John", "last_name": "Smith", "company_name": "Acme Corporation", "tax_id": "123456", "date_of_birth": "1986-01-01", "country_of_birth": "GB", "residential_status": "resident", "billing_address": { "address_line1": "123 High St.", "address_line2": "Flat 456", "city": "London", "zip": "SW1A 1AA", "country": "GB" }, "phone": { "country_code": "+44", "number": "1234 567890" }, "identification": { "type": "passport", "number": "09876", "issuing_country": "US" }, "email": "john.smith@example.com" }, "bank": { "name": "Test Bank", "branch": "Main branch", "address": { "address_line1": "Example Place", "address_line2": "Example Square", "city": "London", "zip": "EC2M 4XY", "country": "GB" } }, "customer": { "id": "cus_y3oqhf46pyzuxjbcn2giaqnb44", "email": "jane.smith@example.com", "name": "Jane Smith", "default": true } } ``` --- ## Update instrument details To update the details of a payment instrument, call the [Update an instrument](https://api-reference.checkout.com/tag/Instruments/#operation/updateInstrument) endpoint, and provide the instrument ID as the `{id}` path parameter. For example, you can update the stored card's expiry month and year, or make the instrument the linked customer's default instrument. > **Information** > > Your base URL's `{prefix}` value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see [API endpoints](https://www.checkout.com/docs/developer-resources/api/api-endpoints.md). **Production** `PATCH` `https://{prefix}.api.checkout.com/instruments/{id}` **Sandbox** `PATCH` `https://{prefix}.api.sandbox.checkout.com/instruments/{id}` ### Request example **Card payment instrument** ```json { "expiry_month": 6, "expiry_year": 2025, "name": "John Smith", "account_holder": { "billing_address": { "address_line1": "123 High St.", "address_line2": "Flat 456", "city": "London", "zip": "SW1A 1AA", "country": "GB" }, "phone": { "country_code": "+44", "number": "1234 567890" } }, "customer": { "id": "cus_gajmdgunwwlehbctuj6a3sifpm", "default": true } } ``` **Bank account payment instrument** ```json { "type": "bank_account", "account_type": "savings", "account_number": "13654567455", "bank_code": "123-456", "branch_code": "6443", "iban": "HU93116000060000000012345676", "bban": "3704 0044 0532 0130 00", "swift_bic": "37040044", "currency": "GBP", "country": "GB", "account_holder": { "type": "individual", "first_name": "John", "last_name": "Smith", "company_name": "Acme Corporation", "tax_id": "123456", "date_of_birth": "1986-01-01", "country_of_birth": "GB", "residential_status": "resident", "billing_address": { "address_line1": "123 High St.", "address_line2": "Flat 456", "city": "London", "zip": "SW1A 1AA", "country": "GB" }, "phone": { "country_code": "+44", "number": "1234 567890" }, "identification": { "type": "passport", "number": "09876", "issuing_country": "US" }, "email": "john.smith@example.com" }, "bank": { "name": "Test Bank", "branch": "Main branch", "address": { "address_line1": "Example Place", "address_line2": "Example Square", "city": "London", "zip": "EC2M 4XY", "country": "GB" } }, "customer": { "id": "cus_y3oqhf46pyzuxjbcn2giaqnb44", "default": true } } ``` ### Response example If successful, you receive a `200` response that contains the updated instrument `fingerprint`. This is a token you can use to identify the card across all customers. **Card payment instrument** ```json { "type": "card", "fingerprint": "vnsdrvikkvre3dtrjjvlm5du4q" } ``` **Bank account payment instrument** ```json { "type": "bank_account", "fingerprint": "smoua2sbuqhupeofwbe77n5nsm" } ``` --- ## Store metadata with an instrument You can attach your own `metadata` object to a card or bank account payment instrument. For example, to store a customer's document number or a partner reference with their card. You can then reference the metadata in [Forward API requests](https://www.checkout.com/docs/payments/store-and-manage-credentials/forward-stored-credentials.md#Metadata_placeholders), so the value is added to every request you forward to a third party, without your systems having to look it up. Metadata is stored encrypted, and is returned exactly as you provided it when you [get instrument details](#Get_instrument_details). It's also returned for each instrument in the `instruments` array when you call the [Get customer details](https://api-reference.checkout.com/tag/Customers/#operation/getCustomerDetails) endpoint. The stored metadata is kept when you update other instrument details, and when [Account Updater](https://www.checkout.com/docs/payments/store-and-manage-credentials/update-stored-credentials.md) refreshes the card details. > **Note** > > Metadata is for your own references. Do not store card details, credentials, or personal data you do not have consent to store. ### Metadata requirements The `metadata` object must be a flat JSON object that meets the following requirements: - A maximum of 20 key-value pairs - Keys between 1 and 100 characters long - Values up to 100 characters long - Keys and values are strings. Nested objects, arrays, numbers, Boolean values, and `null` values are not supported. Keys are case-sensitive. For example, `documentNumber` and `documentnumber` are different keys. If the `metadata` object does not meet these requirements, you receive a `422` response with one or more of the following error codes: | Error code | Reason | | --- | --- | | `too_many_metadata_items` | The object contains more than 20 key-value pairs. | | `metadata_key_invalid` | A key is an empty string. | | `metadata_key_too_long` | A key is longer than 100 characters. | | `metadata_value_too_long` | A value is longer than 100 characters. | | `metadata_value_invalid` | A value is `null`. | | `metadata_only_supported_for_token_type_card` | You provided `metadata` when creating a token with a `type` other than `card`. | If the request fails more than one requirement, you receive an error code for each one. These error codes are also listed in [Error codes](https://www.checkout.com/docs/developer-resources/codes/error-codes.md). ### Add metadata when you create an instrument Provide the `metadata` object in your [Create an instrument](https://api-reference.checkout.com/tag/Instruments/#operation/createAnInstrument) request. You can provide `metadata` for `card`, `bank_account`, and `token` instrument types. If you provide an empty object (`{}`), no metadata is stored. For `token` instruments, an empty object is treated as not provided, so the token's metadata is stored instead. #### Request example ```json { "type": "token", "token": "tok_ubfj2q76miwundwlk72vxt2i7q", "metadata": { "documentNumber": "12345678900" } } ``` #### Response example ```json { "id": "src_wmlfc3zyhqzehihu7giusaaawu", "type": "card", "fingerprint": "vnsdrvikkvre3dtrjjvlm5du4q", "expiry_month": 6, "expiry_year": 2030, "scheme": "VISA", "last4": "4242", "bin": "424242", "metadata": { "documentNumber": "12345678900" } } ``` > **Information** > > If the request matches a payment instrument you've already stored, for example the same card for the same customer, the response returns the existing instrument's metadata. The metadata in your request is not stored. To change it, [update the instrument metadata](#Update_instrument_metadata). #### Create an instrument from a token with metadata If you created a card token with `metadata` using the [Request a token](https://api-reference.checkout.com/tag/Tokens/#operation/requestAToken) endpoint, the metadata is stored with the token for the token's 15-minute lifetime. When you convert the token into a payment instrument: - If you provide a non-empty `metadata` object in the Create an instrument request, the request's metadata is stored in full and the token's metadata is discarded. - If you do not provide `metadata`, or you provide an empty object, the token's metadata is stored with the instrument. The two objects are never merged. You can only provide `metadata` for tokens with the `card` type. ### Update instrument metadata To change the metadata, call the [Update an instrument](https://api-reference.checkout.com/tag/Instruments/#operation/updateInstrument) endpoint and provide the full `metadata` object. You can send a request that only contains `metadata`, without changing any card or bank account details. The `metadata` object you provide replaces the stored object in full. Individual keys are not merged, so to change one key, provide the full object with that key updated. - To remove all metadata, provide an empty object (`{}`). - To keep the stored metadata, do not include `metadata` in the request, or set it to `null`. #### Request example ```json { "metadata": { "documentNumber": "99900011122" } } ``` If successful, you receive a `200` response. If two update requests for the same instrument are processed at the same time, one succeeds and the other returns a `409` response. Get the latest instrument details, reapply your intended change to the full `metadata` object, then send the update again. > **Note** > > The instrument's top-level `metadata` object is separate from the `customer.metadata` object, which belongs to the linked [customer](https://www.checkout.com/docs/payments/store-and-manage-credentials/store-credentials/customers.md). --- ## Delete an instrument To delete a payment instrument, call the [Delete an instrument](https://api-reference.checkout.com/tag/Instruments/#operation/deleteInstrument) endpoint, and provide the instrument ID as the `{id}` path parameter. > **Information** > > Your base URL's `{prefix}` value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see [API endpoints](https://www.checkout.com/docs/developer-resources/api/api-endpoints.md). **Production** `DELETE` `https://{prefix}.api.checkout.com/instruments/{id}` **Sandbox** `DELETE` `https://{prefix}.api.sandbox.checkout.com/instruments/{id}` ### Response If successful, you receive a `204` response. --- ## View stored payment instruments You can view your stored payment instruments in the Dashboard. 1. Sign in to the [Dashboard](https://dashboard.checkout.com). 2. Go to _Vault_ > _Payment instruments_. On this page, you can view: - The total number of stored payment instruments - A breakdown of the types of stored payment instruments – for example, cards and digital wallets Select a payment instrument to view its details, including: - The payment instrument ID - The date the instrument was created - The date the instrument was last modified - The instrument details – for example, the linked customer's ID and the payment method type - The payment method details – for example: - For card payment instruments – The card scheme and card type - For bank-account payment instruments – The bank name and currency