Skip to main content
Cards have no PIN set by default. Until a cardholder sets one, they can enter any PIN at a payment terminal, or skip PIN entry if the terminal allows it. Once a PIN is set, the cardholder must enter the correct PIN for transactions that use PIN verification. Setting a PIN does not require PIN entry for every purchase; transactions that do not request a PIN continue to work without one. These APIs support online PINs only. Offline PINs, which are checked by a card’s chip, are not currently supported. An online PIN is checked over the payment network when a payment requires it. “Online” describes how the PIN is checked; it does not mean the customer is shopping on a website.

Use the hosted PIN-entry iframe

1

Configure your platform

Set cardConfigs.pinTargetOrigin once through PATCH /platform/config:
Use the canonical HTTPS origin of the page that hosts the iframe: scheme, host, and optional port, without a path, trailing slash, credentials, query, or fragment. One origin covers all user-specific paths on that website. Omit this setting in later configuration updates to preserve it, or set it to null to clear it. Changes apply to newly requested URLs.
2

Get a PIN-entry URL

Call GET /cards/{id}/set-pin-url from your backend immediately before displaying the form. Send no request body or origin parameter; Grid uses your platform’s configured origin. If the origin is unset, the request returns 409 CONFLICT.Grid returns iframeUrl, sessionToken, expiresAt, and environment. The URL already contains the temporary token and selects the appropriate environment.Each request creates a fresh, temporary PIN-entry session and returns Cache-Control: no-store. Requesting a URL does not set or change the PIN.
3

Load the form

Before setting the iframe’s src, register a message listener on your page. Only accept messages whose origin equals new URL(iframeUrl).origin and whose source equals your iframe’s contentWindow; also require data.embedType to equal PIN_SETTING.Set the iframe’s src to iframeUrl exactly as returned. Wait for data.messageType to be Embed:Rendered before enabling your submit button. The cardholder enters a four-digit PIN directly into this secure form, so the plaintext PIN never reaches your servers or Grid’s.
4

Submit the PIN

When the cardholder clicks your submit button, send { messageType: "Embed:SubmitPin", embedType: "PIN_SETTING" } to the iframe’s contentWindow using postMessage. Set the target origin to new URL(iframeUrl).origin; never use *. Disable the button while submission is in progress.
5

Confirm the result

Listen for Embed:PinSubmissionStatusChanged with the following data.status values:Remove your event listener when you remove the iframe. If you stop waiting before a result arrives, treat the outcome as unknown: do not report success or automatically resubmit. An OK status alone cannot prove that an already configured PIN was changed.
The session permits one successful submission and expires at expiresAt. Request a new URL for another PIN change or after expiration. Treat both the URL and token as secrets: never persist, cache, log, or send them to analytics.

Encrypt a PIN in your own UI

If you collect the PIN in your own UI, you must encrypt it in the customer’s browser or mobile app before sending it to your server or Grid. Download the PIN encryption public key. This PEM-encoded RSA public key is the same for sandbox and production; save it as pin-encryption-public-key.pem in your client integration.
  1. Collect a four-digit PIN as a string so leading zeros are preserved.
  2. Generate a fresh, cryptographically random integer nonce for each request.
  3. Serialize an object containing nonce and pin as JSON. Encode the JSON as UTF-8.
  4. Encrypt those bytes using the PIN encryption public key, then base64-encode the ciphertext.
  5. Send the base64 string as encryptedPinBlock in POST /cards/{id}/set-pin.
For example, a PIN of 0123 produces JSON with this shape before encryption:
Generate your own nonce each time; do not reuse the example. Encrypt the entire JSON payload. Never send this plaintext object to your server or Grid, and keep both plaintext and ciphertext out of logs, analytics, and persistent storage. Grid cannot decrypt the block. A rejected block returns 400 INVALID_INPUT. Check the payload, encoding, and public key, then create a new encrypted block with a fresh nonce. A 204 response means the PIN change was accepted; read pinStatus from GET /cards/{id} to check its resulting state.

Check and recover a PIN

Read pinStatus from GET /cards/{id}: Three consecutive incorrect attempts block an online PIN. Call POST /cards/{id}/pin/unblock to keep the same PIN, or use either PIN-entry flow to choose a new one. Unblocking a PIN that is already OK is safe; a card with no PIN returns 409 CONFLICT. There is no PIN-reveal API. If the cardholder forgets the PIN, let them set a new one. Setting a PIN does not activate a closed or frozen card or change its spending limits. Card.pinStatus is the last known PIN status, populated when a card with PIN management is created. An absent value means PIN management is unavailable for this card; it does not mean NOT_SET or tell you whether a payment requires a PIN.

Receive PIN status changes

Handle CARD.PIN_STATUS_CHANGE at your webhook endpoint to keep your app’s PIN status up to date. The event contains the updated Card resource in data, including pinStatus.
  • NOT_SET → OK: a PIN was configured.
  • OK → BLOCKED: the PIN became blocked.
  • BLOCKED → OK: the PIN was unblocked or replaced.
Grid sends this event when its saved status changes, including changes detected after an iframe submission or a PIN API request. Initial card creation and replacing a PIN while the status stays OK do not trigger it. Use the iframe submission result or PIN API response to confirm a PIN replacement. Verify the webhook signature and deduplicate deliveries by event id. Deliveries may arrive out of order; use data.updatedAt to avoid overwriting a newer card snapshot. See Card webhooks for payloads and retry behavior.

Offline PIN cards are not supported

An offline PIN is checked by a physical card’s chip. Physical cards can also use online PINs; the distinction is where the PIN is checked.