---
title: Tokenize a contact credit card
slug: tokenize-a-contact-credit-card
docTags: 
createdAt: 2026-02-20T22:12:25.261Z
---

:::hint{type="warning"}
To enable card-on-file features such as this one, you must contact [Jetpay support ](mailto\:jetpay@baselinepayments.com)directly.
:::

Use this flow when you want to securely store a customer's credit card for future payments.

This is typically used if your platform allows users to save cards to their account, you want to support one-click payments, and/or you plan to use the [direct charge](docId\:fQy5afJMMgJ3h5ioYttFd) or [preauthorize and capture](docId:24zJOsKsikmhbluvDyMgq) flows.

Unlike [adding contact bank accounts](docId\:VR87T15eAcOHe-60cKEQv), card details are never handled by your servers. Jetpay provides a secure hosted tokenization component that communicates directly with the card network.

***

## Prerequisites

- [Jetpay API Key](docId:_zgmIm7QKrrAoX9JjaQrL)
- [An existing Jetpay Contact ID](docId\:BzwF0wyOoqBKGSFuGEnH0)
- A configured webhook endpoint to receive tokenization events

***

## Flow overview

```mermaid
sequenceDiagram
    actor Customer
    participant Platform Frontend
    participant Platform Backend
    participant Jetpay API
    participant Card Service

    Platform Backend->>Jetpay API: POST /contact/{identifier}/creditCards/url
    Jetpay API-->>Platform Backend: url + credit_card_id

    Platform Backend-->>Platform Frontend: url

    Platform Frontend->>Customer: Render iframe (url)
    Customer->>Jetpay API: Enter card details (via hosted iframe)

    Jetpay API->>Card Service: Tokenize card
    Card Service-->>Jetpay API: Tokenization result

    Jetpay API-->>Platform Backend: Webhook: credit_card_tokenized (success/failure)
```

***

## Implementation details

### Request a single-use tokenization URL

Endpoint: [`POST /contact/{identifier}/creditCards/url`](https://extapi.jetpay.baselinepayments.com/docs#tag/Contacts-\(v0\)/operation/generate_credit_card_tokenization_url_contact__identifier__creditCards_url_post)

:::CodeblockTabs
```curl
curl https://extapi.demo.jetpay.baselinepayments.com/contact/contact_123/creditCards/url \
  -X POST \
  -H "Authorization: Bearer <YOUR_API_TOKEN>" \
  -H "Content-Type: application/json"
```

```python
import requests

BASE_URL = "https://extapi.demo.jetpay.baselinepayments.com"
API_TOKEN = "<YOUR_API_TOKEN>"
CONTACT_ID = "contact_123"

url = f"{BASE_URL}/contact/{CONTACT_ID}/creditCards/url"

headers = {
    "Authorization": f"Bearer {API_TOKEN}",
    "Content-Type": "application/json"
}

response = requests.post(url, headers=headers)

print("Status Code:", response.status_code)
print("Response Body:", response.json())
```

```nodejs
const BASE_URL = "https://extapi.demo.jetpay.baselinepayments.com";
const API_TOKEN = "<YOUR_API_TOKEN>";
const CONTACT_ID = "contact_123";

async function createTokenizationSession() {
  const response = await fetch(
    `${BASE_URL}/contact/${CONTACT_ID}/creditCards/url`,
    {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${API_TOKEN}`,
        "Content-Type": "application/json"
      }
    }
  );

  const data = await response.json();

  console.log("Status Code:", response.status);
  console.log("Response Body:", data);
}

createTokenizationSession();
```
:::

The API will respond with an HTTP response code of 200, and the following response body:

```json
{
  "url": "https://secure.jetpay.com/tokenize/session_abc",
  "credit_card_id": "card_456"
}
```

You should store the `credit_card_id` immediately, **but the card is not usable until tokenization succeeds.**

### Display the hosted card component

::::VerticalSplit{layout="middle"}
:::VerticalSplitItem
Render the returned `url` inside an iframe in your frontend.

Card details are entered directly into Jetpay's secure environment. Card info is never exposed to your frontend and never transmitted through your backend.

This significantly reduces your PCI scope.
:::

:::VerticalSplitItem


![](https://api.archbee.com/api/optimize/22RTQMLnemxhvi7pdhX-s/31AAAgDPTNLJqb-mJI5md-20260219-193523.png)
:::
::::

### Wait for tokenization confirmation (webhook)

Once the customer submits their card details, Jetpay processes the tokenization. Although this process is typically quite fast, it can take up to a couple minutes. Therefore, we will send you [credit card tokenization success ](docId:-bnN6n5bf_AFNEr-9SDdr)webhook event indicating that the tokenization succeeded.

Only **after** receiving a successful event should you mark the card as active in your system and allow it to be selected for payments.

Do not assume success based on iframe behaviour alone.

***

## Using the tokenized credit card

With a Contact (`contact_id`) and a tokenized credit card (`credit_card_id`), you can proceed with the following credit card payment flows:

- [Directly charge a credit card](docId\:fQy5afJMMgJ3h5ioYttFd)
- [Preauthorize and capture](docId:24zJOsKsikmhbluvDyMgq)&#x20;

If you are unsure of exactly what flow fits your use case, check out the [Find your use case](docId\:unBjNk_Vn-70W4Vs_ZD9o) and [Receive payments](docId:08LAM2GI8077ASxe8snp6) guides.

