Skip to main content
Once Payra Elements has collected a card or a bank account and the session is succeeded, your server turns it into a payment method: a pm_test_… / pm_live_… object that names the instrument as far as you may see it (a card’s brand, last four digits and expiration date; a bank account’s last four digits, account type and holder type, plus the institution and transit numbers of a Canadian one) and that your server charges. The tokenized details stay inside Payra and never appear in a response. Where Payra has enabled it, your server can also send a US bank account it already holds instead of a session.
1

Get the session id back on your server

Your page already has it: confirmPaymentMethodSession resolves with { paymentMethodSession }, and your server created it. Send the id to your backend the way you send any form result. Nothing secret travels: the id alone cannot collect, charge or read anything.
2

Create the payment method with your secret key

Response
type says which block is set, the other being null. A bank account collected without a customer reads:
A Canadian account reads type: "acss_debit", with its block in acss_debit (last4, account_type, account_holder_type, institution_number, transit_number) and no billing postal code, which a Canadian debit does not take.Each session creates one payment method. A second call with the same session answers 400 payment_method_session_used, naming the method it already created; a retry with the same Idempotency-Key answers the first response again. Create the method soon after the confirm: a session that succeeded more than 30 minutes ago answers 400 payment_method_session_inactive.
3

Keep the id

Store pm_… with your customer or order. Read it back any time with retrieve; the session also carries it as payment_method.

Saved or one-time

The session decides, when your server creates it, unless you say otherwise when you create the payment method: Sending usage lets your page bind the session to a signed-in buyer before they decide whether to keep the card, and send their choice with the create: account_holder_authorization: true to save it, usage: "one_time" not to. The card fields never need a new session when the buyer changes their mind. usage: "saved" on a session without a customer answers 400 parameter_invalid on usage. A bank account follows its session only: with a customer it is kept under its standing authorization. A card the customer already has on file, in the same currency, is not saved twice. The create answers 200 instead of 201, with the payment method that already holds the card, and gives the session back, so a retry under a new Idempotency-Key gets the same answer. When the buyer typed a new expiry, name or postal code, Payra verifies the card again with them and the method keeps its id. Cards are matched among those collected with Elements: one your team saved in the Payra dashboard counts as a different card. At checkout you can skip this call: charge the session itself, and keep the card with its first payment, by sending payment_method_session and save_payment_method: true to the payment. The charge proves the card, so Payra runs no separate verification where the processor allows it, and the checkout is faster. Saving a card needs a billing postal code. Elements has no postal code field: collect it on your page and pass it as billingDetails.postalCode when you confirm the session, or the create answers 400 parameter_invalid on billing_details.postal_code. It must be a US ZIP or a Canadian postal code; a malformed one already fails the confirm, with 400 parameter_invalid on billing_postal_code. A bank account carries its own authorization, so account_holder_authorization is not used: the account holder accepted the ACH authorization (on a Canadian account, the pre-authorized debit agreement) in Elements, and Payra kept the record. Saved with a customer, the account is verified with the workspace’s processor and kept on file under that standing authorization (for a Canadian account, the combined PAD agreement) until the account is removed from the customer’s file, by your server (detach), by your team in the Payra dashboard or by the customer in the customer portal (the method then reads detached). Without a customer it can be debited once, within 30 minutes, for exactly the amount its session named.

Let the bank authenticate a card you save (3-D Secure)

Where Payra has turned 3-D Secure on for your workspace, the cardholder’s bank can authenticate a card before it is saved on a customer. Ask for it when you create the payment method, by saying how your page takes the bank’s step: Send one, not both. Without either, the card is saved without the bank’s step, as before.
Response
  1. When the bank wants a step, the create answers 201 with status: "requires_action" and a next_action. Nothing is saved yet: the method is not on the customer’s list and cannot be charged (400 payment_method_unusable).
  2. Run the step: handleNextAction on your page, or send the cardholder to next_action.url.
  3. Read the payment method on your server (retrieve) before you charge it or show it as saved. It reads active once the bank authenticated the card and it is saved, with the same id, or failed with a failure.
A failed method keeps its session: collect the card again with a new session to retry. When the bank authenticates without a step, the create answers active at once. When the bank does not take part in 3-D Secure, or 3-D Secure is unavailable, the card is saved without it, as it would be without the parameter. When the bank refuses at once, the create answers 402 card_authentication_failed and saves nothing. No webhook is sent for a payment method: read it.

A card the customer already has

A card the customer already has saved is not saved twice: the create answers 200 with its saved payment method, as above. When that card was collected again with a new expiry, name or postal code, the bank can still ask for its step before the new details are saved. No second payment method is made:
  • The create answers 200 with the saved method, its status still active, and a next_action.
  • Run the step the same way (handleNextAction, or send the cardholder to next_action.url).
  • The method can be charged meanwhile, with the details it has. It takes the new ones once the bank authenticated the card, and keeps the ones it has when the bank did not or the cardholder left the step. failure stays null either way: the card is still saved.
So run next_action whenever a payment method carries one, not only when it reads requires_action.

Send bank details from your server

Where Payra has enabled it for your workspace, your server can send a US bank account it already holds, keyed in a virtual terminal or taken on a form of your own, instead of collecting it with Elements. The request carries the account in place of session, and your attestation that the account holder authorized the debit. It needs an Idempotency-Key.
The answer is the same payment_method object a session gives. Payra puts the numbers in its vault and keeps the account number only as a token and its last four digits.
  • customer or amount. With customer, the account is verified with the workspace’s processor and saved on the customer’s file under a standing authorization (usage: saved). With amount (in cents, USD), it can be debited once, within 30 minutes, for exactly that amount (usage: one_time): charge it like any one-time payment method. Send one of the two. usage and account_holder_authorization do not apply here and are refused.
  • ach_authorization is your attestation. method is how the account holder authorized the debit: verbal (by phone), written (a signed form), or online_checkbox (a form on your own page). accepted_at is when they did, and cannot be in the future. ip_address and user_agent are the account holder’s, when you have them, never your server’s. Payra records the authorization as your statement (“I confirm the customer authorized…”, the session’s full_text), not as the account holder accepting Payra’s terms. In it you also confirm that, for a one-time debit authorized by phone, the call was recorded or written confirmation was sent before the debit settles, and that you keep the original authorization for two years after it ends.
  • Checked before anything is stored. routing_number must be a valid US routing number (nine digits, a prefix the Federal Reserve issues, a valid check digit), and account_number 7 to 17 digits. Otherwise the answer is 400 parameter_invalid, naming the field and never the value. customer must be one of yours, and active.
  • Payra makes the session. The method’s session names it; read it with retrieve to see the authorization as recorded, with ach_authorization.method as you sent it.

Lifecycle

List a customer’s saved payment methods

To show a returning buyer the cards they saved, list them by customer:
Response
The list holds the customer’s saved payment methods that can still be charged, newest first, in the environment of your key: detached ones are left out. It pages with limit and starting_after. Only methods made through this API are listed: a card your team saved in the Payra dashboard, or the customer in the customer portal, has no payment method id. An unknown customer answers 400 parameter_invalid on customer.

Detach a saved payment method

When the buyer removes a card from their account on your side, remove it from their Payra file too:
The answer is the payment method, now status: detached. It can no longer be charged, and it leaves the customer’s file in the dashboard, as when your team removes it there. Detaching a method that is already detached answers it again, unchanged. A one-time method belongs to no one and cannot be detached (400 parameter_invalid on id): it expires on its own. Detaching needs payment_methods:write.

Errors on create

What a payment method never carries

The tokenized card number and security code, the tokenized routing and account numbers, or any processor reference. Payment methods belong to the workspace and environment of the key that created them: a pm_test_… read with a live key, or with another workspace’s key, answers 404 resource_missing.