Skip to main content

PIN management

Let cardholders set or reset the PIN of their physical card, without your servers ever handling the digits in the clear.

A PIN is used where a card is presented at a terminal or a machine, so it belongs to a physical card. Virtual cards don't have one.

Before you begin​

You'll need:

  • An active physical card. See issuing a physical card. Activate the card first: a card that isn't active is refused.
  • An app that can encrypt on the cardholder's device with RSA-OAEP using SHA-256.
  • The cards:secrets scope on your credential. This scope isn't enabled by default.

How it works​

The cardholder types their PIN into your app. The app encrypts it on the device to a short-lived key we issue, and your backend passes the ciphertext to us. Your servers only ever hold something they can't read.

The same two calls set a PIN for the first time and reset an existing one.

Steps​

1. Get an encryption key​

Call Get a PIN encryption key when the cardholder is about to enter their PIN, not when the screen loads. The key is for one card, expires after a few minutes, and opens one PIN: once it has been sent with a PIN, whatever the outcome, it can't be used again.

2. Encrypt the PIN on the device​

Encrypt the PIN, as its digits, to the key's public key with RSA-OAEP using SHA-256, and encode the result as base64. Do it on the cardholder's device and send only the ciphertext to your backend. A PIN that your servers handle as readable text puts those servers in PCI DSS scope.

Validate the PIN on the device before you encrypt it. We only require digits, in the length the key response gives as pin_length. Every other rule is yours, such as refusing repeated digits or sequences, so the cardholder is told at once and nothing weak is sent. See PCI DSS scope.

3. Set the PIN​

Call Set a PIN with the key_id and the encrypted PIN. A successful call returns nothing.

Never write the PIN, encrypted or not, to a log, an analytics event, web storage or a support ticket.

Verifying​

  • Setting a PIN returns no content, and no response carries a PIN.
  • A key that is unknown, has expired or was used already is refused. Get a new one.
  • A PIN that isn't digits of the right length, or that can't be decrypted with the key you were given, is refused with pin_invalid. We apply no other rule.
  • A virtual card, or a card that isn't active, is refused with card_invalid_state.
  • A credential without cards:secrets returns insufficient_scope.

Common errors​

StatuscodeFix
400missing_parameterkey_id or encrypted_pin wasn't sent
400invalid_parameterThe key is unknown, has expired or was already used. Get a new key
403insufficient_scopeThe credential doesn't have cards:secrets
404card_not_foundThe card doesn't exist, or belongs to another organization
404not_foundThis program can't take a PIN by a call, so the route isn't available
422pin_invalidThe PIN isn't the right length, isn't digits, or wasn't encrypted to the key you were given
422card_invalid_stateThe card is virtual, or isn't active. A PIN is set on an active physical card
422card_closedThe card is closed. Issue a new card
422program_not_configuredThe program isn't set up to take a PIN. Raise it with your account contact
502processor_permission_deniedThe program isn't approved to set PINs at the processor. Send us the request_id
502processor_unavailableThe outcome is unknown: the PIN may or may not be set. Don't resend on your own; ask the cardholder to try again, with a new key