Save a payment method without charging it
Stores a card, bank account or wallet against an account as a saved payment method, tokenised at the gateway, without taking a payment. Support staff use it from the account screen to put a customer's new card on file over the phone; customers use it from the hosted checkout when a checkout request asks for a method to be saved, and integrators call the API directly. The same call can name contracts the new method should be attached to, and can register a token the integrator already holds at the gateway.
Where you can do this
- Merchant View: Account (Add Payment Method)
- Merchant View: Account header (Add Payment Method)
- The hosted checkout: Payment form (Confirm (confirm page, TOKENISE); the gateway's own save-card page (hosted))
- API: Create a checkout (
POST /checkouts) — action TOKENISE for an account; prepares the checkout, the save itself is the POST below - The hosted checkout: the hosted checkout submits in TOKENISE mode; the hosted checkout forwards it to POST /c/api/payment_methods
- API: Create a payment method (
POST /payment_methods) — body carries card, bank or wallet details, or the id of a saved method; with token it registers a token already held at the gateway without calling it - Automatically (Shuttle): gateway return for a redirect-based method — the provider's connector receives the customer's return or webhook and posts the token to Shuttle, which activates the method and attaches any contracts parked on it
Before you start
- An account, named by id or CRM key, or account details from which one can be registered or created anonymously (the channel must allow that).
- A gateway that can save cards or create tokens for the card type, either named in the call or reachable through the initiative's routing for the account's country.
- For a saved method named by
id, that method must be ACTIVE or FAILING. - For a token registered directly, the gateway must exist and the token must be supplied.
Inputs
Fields on POST /c/api/payment_methods, inside payment_method:
| Input | Required | Meaning and constraints |
|---|---|---|
| account | yes | An account id, or an object: id, or crm_key (alias alt_key) with first_name, last_name, company, email, phone, address (country, line1 to line6) and tags. With crm_key and no id the most recently created account with that CRM key is used, or one is registered through the channel. With neither, an anonymous account is created from the details |
| id | no | A saved payment method to reuse; nothing new is stored or tokenised, the call only attaches it to contracts |
| gateway | conditional | Required with token. Otherwise optional: when omitted the gateway is chosen by routing (initiative, the account's country, card type) |
| currency | no | Passed to the gateway with the tokenisation |
| code | no | Reporting code for the method; must not be in use by an ACTIVE or FAILING method |
| nonce | no | Serialises concurrent calls carrying the same value and is stored on the method. A payment-link nonce (pl_...) marks that link complete once the method is ACTIVE |
| type | no | Card type (alias card_type). Derived from card_number when omitted; SEPA, ACH or BACS is inferred from the bank fields |
| card_number | conditional | One of a card, bank or wallet detail set is needed for a new method. Non-digits are stripped |
| card_expiry | no | Alias expiry. Accepts MMYY, MM/YY, M/YY or MYY and is stored as a month; other formats are not stored |
| card_cvc | no | Passed to the gateway, never stored |
| last4 | no | Alias card_ending |
| bin | no | Alias card_bin |
| requires_cvc | no | Marks the saved method as needing a CVC on later use |
| iban | conditional | Alias sepa_iban; makes the method SEPA |
| account_holder_name | no | Aliases cardholder_name, card_holder_name, sepa_account_holder_name, ach_account_holder_name |
| account_type | conditional | Alias ach_account_type; makes the method ACH |
| routing_number | no | Alias ach_routing_number |
| account_number | conditional | Alias ach_account_number; makes the method BACS when no other type applies |
| name | no | Alias description. Stored as the method's description, localised with the card type and ending |
| address | no | Alias billing. Billing address (country, line1 to line6) sent to the gateway and stored |
| tags | no | Stored on the method |
| metadata | no | Stored on the method |
| source | no | ecommerce (default), moto, pos or recurring; sets whether the customer and staff are present, which the gateway is told and the method records |
| success_url | no | Where a redirect-based method returns on success; #PAYMENTMETHODKEY# is replaced and payment_method=pm_... appended |
| cancel_url | no | As success_url, for a cancelled or failed authorisation |
| locale | no | As user_agent |
| token | conditional | A token already held at the gateway. Switches the call to registration: no gateway call is made and the method is stored with status (default ACTIVE), sub_status and sub_status_reason as sent |
| manual | no | Same effect as sending token |
| contracts[] | no | Contracts to attach the method to; see Change the payment method on a contract |
Fields on POST /c/api/checkout for this function: action TOKENISE (required), force_add (hides the account's saved methods so a new one must be entered; Merchant View always sets it), legal_entity (narrows the gateways the form offers), and the checkout fields that belong to Take a one-off payment (nonce, account, channel, source, currency) and to Change the payment method on a contract (contracts[]).
Rules
Checked by the API means Shuttle refuses the request however it is sent; a screen name means only that screen refuses it, and a direct API call would be accepted.
| Rule | Checked by | What you see |
|---|---|---|
| The checkout call follows the checkout rules of Take a one-off payment (body, nonce, CRM key without spaces, duplicate nonce) | The API | see Take a one-off payment |
| An account is required | The API | VALIDATION_ERROR: "Missing account" |
| A token registered directly needs a gateway | The API | VALIDATION_ERROR: "Missing gateway" |
| A CRM key must not contain spaces | The API | VALIDATION_ERROR: "crm_key cannot inlcude spaces" (sic) |
A customer's account session may only save a method on its own account; the check is on the account, whether given by id or resolved from crm_key | The API | NO_PERMISSION: "No permissions"; Shuttle: INVALID (BOLT-1005) |
An account object with neither id nor crm_key creates an anonymous account, which the channel must allow | The API | INVALID (BOLT-1086, anonymous accounts disabled) |
An account named by crm_key that the CRM does not know is refused unless the channel allows registration | The API | INVALID (BOLT-1031 with registration on, BOLT-1087 with it off) |
| The account must resolve; when creating one fails for any reason other than fraud the failure is swallowed and the call fails on the missing account | The API | INVALID (BOLT-1031) |
| A merged account resolves to the account it was merged into; the method is stored there | The API | silent (see Link a duplicate account) |
| Every call creates a customer session for the account and runs the fraud screening on it; a blocked session refuses the call with the screening's reason | The API | INVALID (BOLT-1088) with the fraud reason as the message |
| The channel must exist and accept payments | The API | INVALID: "Invalid value for field channelKey." / channel not accepting payments |
A saved method named by id must exist and be ACTIVE or FAILING. It is attached to contracts only when ACTIVE; a FAILING method returns OK and changes nothing | The API | NOT_FOUND on "payment_method |
Each contract in contracts[] must exist and be in a status that accepts a new method; the set and the attach rules are on Change the payment method on a contract | The API | INVALID on "contract: |
code must not be in use by an ACTIVE or FAILING method | The API | INVALID: "Invalid code" |
| The card type is derived from the card number when not sent; a number whose type cannot be recognised is refused | The API | INVALID (BOLT-1093) |
| A card expiry of December in the current year, or on the test card ending 1111, is not stored (test-card convention) | The API | silent; the method shows no expiry |
A named gateway must exist and have a payment processor; when none is named, the initiative's routing for the account's country and the card type must reach one. A legal_entity in the body plays no part in this routing, and no part in anything else: it is dropped on the way in | The API | INVALID (BOLT-1095 named gateway; BOLT-1105 no route) |
| The gateway must offer card saving or token creation for the card type; checked only when a card type is known, so a call with no recognisable type skips it | The API | INVALID (BOLT-1096, tokenisation not available) |
| The gateway call itself failing (a connector error rather than a decline) abandons the call; nothing is stored | The API | INVALID (BOLT-1167) with the gateway's messages |
A gateway decline is not an error: the method is stored INACTIVE with the gateway's reason in gateway_status and the call returns OK. Callers must read status; the hosted checkout does and shows the reason | The API and the hosted checkout | OK with status INACTIVE |
| Only one call per nonce runs at a time (a random one when none is sent); a second call with the same nonce while the first runs fails at once rather than waiting | The API | INVALID (BOLT-7059) |
| The nonce does not stop duplicates: once the first call completes, a second call with the same nonce and details stores a second method. Only a payment carries a duplicate-nonce rule (see Take a one-off payment) | The API | silent; two methods |
| From the hosted checkout, calls that reuse the same saved method id are serialised for 60 seconds and a second call within 5 seconds receives the first call's result; a new-card submission is keyed by the clock, so nothing serialises it beyond the nonce rule above | The API | second call waits, or gets the first result |
| the hosted checkout offers a gateway for saving only when it can save cards or create tokens for the card type, the currency matches, the gateway is not running down and its routing rules allow the card; a currency whose maximum amount rule is zero is treated as disabled for saving | The hosted checkout | gateway or currency not offered |
Registering a token directly: the gateway must exist, token is mandatory, code must be unique, and the session needs account on the account | The API | NOT_FOUND on "payment_gateway |
| Merchant View offers Add Payment Method only when the account's division has a WEB channel; the server has no such rule | Merchant View screen | control hidden |
What happens
- A new saved method appears on the account and in the response, with
statusACTIVE (ready to use;sub_statusPENDING where a mandate is still being set up), REQAUTH with anauthorisation_urlthe customer must complete, or INACTIVE with the gateway's reason ingateway_status. Nothing is charged. - Where
contracts[]was sent, those contracts switch to the new method as soon as it is ACTIVE (at once, or when the customer completes the authorisation) and any outstanding amount is collected straight away; see Change the payment method on a contract. the hosted checkout warns the customer of that before they confirm. - Webhook subscribers receive PAYMENT_METHOD.CREATED, then PAYMENT_METHOD.ACTIVE, PAYMENT_METHOD.PENDING or PAYMENT_METHOD.FAILED, and CONTRACT.UPDATE for each contract attached; a redirect-based method raises PAYMENT_METHOD.UPDATE and PAYMENT_METHOD.ACTIVE when it completes.
- An account named by CRM key that Shuttle did not know is registered; details sent with an existing account update its CRM record; an anonymous account is created when neither id nor CRM key is sent. In Merchant View the account screen reloads its saved methods when the checkout reports success.
- A payment link whose nonce was used is marked complete with the method.
- No email or SMS is sent by the tokenisation itself.
Who can do this
- Roles: Admin only today; intended for Support as well, and being aligned. Support holds
accountbut Merchant View gates the control onpayment_contract. From the hosted checkout, no operator role applies. - Admin app: the
moto_tokenisedashboard option, a WEB channel on the division, and a legal entity chosen when the division has more than one active; applies to the admin entry points only. - Checkout form:
force_addhides saved methods; a gateway feature can skip the confirm step; the save-card toggle is hidden in tokenise mode because saving is the point of the request.
Related
Updated 11 minutes ago