> For the complete documentation index, see [llms.txt](https://docs.coda.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.coda.co/codapay/additional-features/saving-card-details-new-notification.md).

# Saving Card Details - New Notification

### Overview

Codapay supports saving card details for returning users to simplify and accelerate checkout. This capability is available on the Hosted Payment Page for eligible merchants and enabled card schemes.

When enabled, users can store their card securely during checkout and reuse it in future transactions.

> ⚠️ **Note:** This feature is **not currently available** for **India and Indonesia**

### Eligibility and Activation

Saved card functionality is only available for merchants who have been explicitly enabled for this feature.

To enable saved card functionality, contact your Codapay account manager or support team.

If a merchant is not enabled, the payment is processed normally but card details are not saved. A warning is returned in the `/v2.0/Payment/init.json` response in these cases.

### User Identification & Shopper Mapping

Users must be logged into your platform before initiating a payment that involves saving or using a saved card.

You are required to pass a `partner_shopper_id` in the `/v2.0/Payment/init.json` request. This field represents the unique user ID in your system. It must:

* Uniquely identify a single user
* Remain consistent across all sessions and devices
* Be included in every saved card–related request

When the first saved card is added, Codapay creates a `shopper_id` and links it to the provided `partner_shopper_id`. All saved cards are then associated with this `shopper_id`.

Codapay uses this linkage to:

* Retrieve saved cards in future checkouts
* Attach newly saved cards to the correct user
* Process recurring or merchant initiated payments without additional user input

### Integration Overview

To enable saved card functionality on the Hosted Payment Page, include the following fields in your `/v2.0/Payment/init.json` request:

<table><thead><tr><th width="284.62109375">Field</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>enableSavePaymentMethod</code></td><td>Boolean</td><td>Enables the option for users to save their card</td></tr><tr><td><code>displaySavedPaymentMethodList</code></td><td>Boolean</td><td>Displays previously saved cards to the user</td></tr><tr><td><code>userInitiated</code></td><td>Boolean</td><td>Indicates whether the user is present in the payment flow</td></tr><tr><td><code>shopper</code></td><td>Object</td><td>Identifies the user and passes billing details used for token creation</td></tr></tbody></table>

#### Shopper Object

The `shopper` field in the `/v2.0/Payment/init.json` request is a list of key-value pairs under `shopper.entry[]`.

Each key corresponds to shopper identity or billing information used to retrieve or create a shopper profile and support saved card functionality.

| Key                   | Required    | Description                                                        |
| --------------------- | ----------- | ------------------------------------------------------------------ |
| `partnerShopperId`    | Yes\*       | Unique user ID from your system                                    |
| `id`                  | No          | Codapay-issued `shopper_id` to retrieve a known shopper            |
| `email`               | No          | Shopper’s email address (required to create a new shopper)         |
| `phoneNumber`         | No          | Shopper’s phone number                                             |
| `billingFirstName`    | No          | Shopper’s first name (required for billing and shopper creation)   |
| `billingLastName`     | No          | Shopper’s last name (required for billing and shopper creation)    |
| `billingDocumentType` | Conditional | Type of national ID document (e.g., CPF), required in some markets |
| `billingDocumentId`   | Conditional | Value of the national ID document, paired with `documentType`      |
| `billingAddress`      | No          | Street address                                                     |
| `billingCity`         | No          | City name                                                          |
| `billingRegion`       | No          | State or province                                                  |
| `billingCountry`      | No          | ISO alpha-2 country code (e.g., `US`)                              |
| `billingZipCode`      | No          | Postal code                                                        |

> \* Required when saving a card for the first time.

* If `id` is present, Codapay attempts to retrieve the existing shopper linked to that `shopper_id`.
* If `id` is not provided, a new shopper is created and linked to the provided `partnerShopperId`.
* Fields listed here are required in addition to the standard fields documented [here](/codapay/hosted-payment-page-integration/initiate-a-payment-request.md#request-parameters).

Refer to the "Scenarios and Examples" section below for request payloads using this structure.

### Scenarios and Examples

This section outlines the most common use cases when integrating saved card functionality. Each use case includes the required parameters and sample request format.

1. [First-Time User - Save Card Option](#id-1.-first-time-user-save-card-option)
2. [Returning User – Show Saved Cards](#id-2.-returning-user-show-saved-cards)
3. [Returning User – Charge Saved Card Without UI](#id-3.-returning-user-charge-saved-card-without-ui)
4. [Merchant-Initiated Payment – User Not Present](#id-4.-merchant-initiated-payment-user-not-present)

#### 1. First-Time User – Save Card Option

Allow the user to save their card during checkout.

![](https://lh7-rt.googleusercontent.com/slidesz/AGV_vUcR11xjyCtJfxQ5bTcAiSf8jqj7Xq7zd5QmG2JCJ6kE3WRcsHHJRBYBBugn4tVnGYenj3O_YkDrQFH8kVLZwlEoBnnEArkE_JiZoYy_Qmwht5OmanUE0CUprPQl0HqKJnIUO8MFCA=s2048?key=gGON4PQ0VryRSm6zbKD4uA)

**Request**

```json
{
  "initRequest": {
    "country": 360,
    "payType": 400,
    "apiKey": "",
    "projectId": "31",
    "orderId": "20250611113402",
    "currency": 360,
    "items": [
      {
        "code": "12ds",
        "price": 10000.00,
        "name": "Star Diamond"
      }
    ],
    "profile": {
      "entry": [
        {
          "key": "user_id",
          "value": "105"
        }
      ]
    },
    "enableSavePaymentMethod": true,
    "displaySavedPaymentMethodList": true,
    "userInitiated": true,
    "shopper": {
      "entry": [
        {
          "key": "partnerShopperId",
          "value": "test_partner_123_Id"
        },
        {
          "key": "email",
          "value": "test@example.com"
        }
      ]
    }
  }
}
```

**Response**

```json
{
  "initResult": {
    "resultCode": 0,
    "txnId": 7503012627171645973
  }
}
```

**Merchant Notification**

```json
{
  "eventType": "PAYMENT_METHOD_ADDED",
  "timestamp": "2025-06-19T02:48:39.568907Z",
  "shopper": {
    "id": "shp_sg197861636b40021",
    "partner_shopper_id": "test_partner_123_Id",
    "email": "test@example.com"
  },
  "paymentMethod": {
    "id": "pmt_sg1978616a1900024",
    "type": "card",
    "card": {
      "lastFour": "7263",
      "expirationMonth": "04",
      "expirationYear": "2027"
    }
  }
}
```

#### 2. Returning User – Show Saved Cards

Display previously saved cards to the user for selection.

![](https://lh7-rt.googleusercontent.com/slidesz/AGV_vUdEAGAY5Zx2GS16XZ0bw30Q9tSX35CLiL6M2JdqGjnrZjyRCwsYRJAKsu0sj6_1SvG4nVrJM4ou-cSJwm4YgROv6i47bCv-HlXYzLYmpWOyyjnhQUDBVmYJUMtT0xFuQ-QveiqUwQ=s2048?key=gGON4PQ0VryRSm6zbKD4uA)

**Request**

```json
{
  "initRequest": {
    "country": 360,
    "payType": 400,
    "apiKey": "",
    "projectId": "31",
    "orderId": "20250611113402",
    "currency": 360,
    "items": [
      {
        "code": "12ds",
        "price": 10000.00,
        "name": "Star Diamond"
      }
    ],
    "profile": {
      "entry": [
        {
          "key": "user_id",
          "value": "105"
        }
      ]
    },
    "enableSavePaymentMethod": true,
    "displaySavedPaymentMethodList": true,
    "userInitiated": true,
    "shopper": {
      "entry": [
        {
          "key": "id",
          "value": "shp_sg197861636b40021"
        }
      ]
    }
  }
}
```

**Response**

```json
{
  "initResult": {
    "resultCode": 0,
    "txnId": 7503016855911597963
  }
}
```

#### 3.  \[Coming Soon] Returning User – Charge Saved Card Without UI

**Request**

```json
{
  "initRequest": {
    "country": 360,
    "payType": 400,
    "apiKey": "",
    "projectId": "31",
    "orderId": "20250611113402",
    "currency": 360,
    "items": [
      {
        "code": "12ds",
        "price": 10000.00,
        "name": "Star Diamond"
      }
    ],
    "profile": {
      "entry": [
        {
          "key": "user_id",
          "value": "105"
        }
      ]
    },
    "enableSavePaymentMethod": true,
    "displaySavedPaymentMethodList": false,
    "userInitiated": true,
    "shopper": {
      "entry": [
        {
          "key": "id",
          "value": "shp_sg197861636b40021"
        }
      ]
    }
  }
}
```

**Response**

```json
{
  "initResult": {
    "resultCode": 0,
    "txnId": 7503016855911597963
  }
}
```

#### 4.  \[Coming Soon] Merchant-Initiated Payment – User Not Present

**Request**

```json
{
  "initRequest": {
    "country": 360,
    "payType": 400,
    "apiKey": "",
    "projectId": "31",
    "orderId": "20250611113402",
    "currency": 360,
    "items": [
      {
        "code": "12ds",
        "price": 10000.00,
        "name": "Star Diamond"
      }
    ],
    "profile": {
      "entry": [
        {
          "key": "user_id",
          "value": "105"
        }
      ]
    },
    "enableSavePaymentMethod": true,
    "displaySavedPaymentMethodList": false,
    "userInitiated": false,
    "shopper": {
      "entry": [
        {
          "key": "id",
          "value": "shp_sg197861636b40021"
        }
      ]
    }
  }
}
```

**Response**

```json
{
  "initResult": {
    "resultCode": 0,
    "txnId": 7503016855911597963
  }
}
```

### Webhook Notifications

Codapay sends real-time notifications to your configured webhook endpoint when a card is successfully saved.

These events allow you to track and reconcile saved card activity with your own user records.

#### PAYMENT\_METHOD\_ADDED

This notification is sent when a new card is successfully saved and linked to the shopper profile.

**Notification Payload**

```json
{
  "eventType": "PAYMENT_METHOD_ADDED",
  "timestamp": "2025-06-19T02:48:39.568907Z",
  "shopper": {
    "id": "shp_sg197861636b40021",
    "partner_shopper_id": "test_partner_123_Id",
    "email": "test@example.com"
  },
  "paymentMethod": {
    "id": "pmt_sg1978616a1900024",
    "type": "card",
    "card": {
      "lastFour": "7263",
      "expirationMonth": "04",
      "expirationYear": "2027"
    }
  }
}
```

**Field Details**

| Field                                | Description                               |
| ------------------------------------ | ----------------------------------------- |
| `eventType`                          | Event type: always `PAYMENT_METHOD_ADDED` |
| `timestamp`                          | Time the payment method was saved         |
| `shopper.id`                         | Codapay-assigned shopper ID               |
| `shopper.partner_shopper_id`         | Merchant-side user ID passed during init  |
| `shopper.email`                      | Shopper's email                           |
| `paymentMethod.id`                   | Internal Codapay ID for the saved card    |
| `paymentMethod.type`                 | Payment method type – e.g. `card`         |
| `paymentMethod.card.lastFour`        | Last 4 digits of the card number          |
| `paymentMethod.card.expirationMonth` | Card expiry month (MM)                    |
| `paymentMethod.card.expirationYear`  | Card expiry year (YYYY)                   |

***

* Codapay expects a 2xx HTTP response to mark a notification as successfully received.
* If a non-2xx response is received, the notification is retried.
* You can match events using `shopper.id` to your internal user ID.
* Each notification is signed. You must verify the checksum to ensure authenticity. Refer to [Implement Checksum](/codapay/integration-guides/security-guidelines.md#implement-checksum) for implementation details.

***

### Webhook Notifications

### Event Types

For Codapay integrations, your endpoint should be prepared to handle the following `eventType` values:

| Event Type               | Description                                          |
| ------------------------ | ---------------------------------------------------- |
| `SHOPPER_CREATED`        | The new shopper profile is created.                  |
| `PAYMENT_METHOD_ADDED`   | The shopper successfully saved a new payment method. |
| `PAYMENT_METHOD_REMOVED` | The shopper removed a saved payment method.          |
| `PAYMENT_SUCCESSFUL`     | The payment transaction is successfully completed.   |
| `PAYMENT_FAILED`         | The payment transaction failed                       |

### Notification Payload Structure

Notifications are sent as a `POST` request with a JSON body.

<table><thead><tr><th width="185.33203125">Field</th><th width="117.671875">Type</th><th>Description</th></tr></thead><tbody><tr><td>eventType</td><td>string</td><td>The specific event type being reported (e.g., <code>CAPTURE_SUCCESSFUL</code>)</td></tr><tr><td>txnId</td><td>string</td><td>The unique transaction ID generated by Coda</td></tr><tr><td>orderId</td><td>string</td><td>The merchant-side unique identifier for the order</td></tr><tr><td>checksum</td><td>string</td><td>A security hash used to verify that the notification payload has not been tampered with</td></tr><tr><td>chargedAt</td><td>string</td><td>Timestamp indicating when the transaction was processed.</td></tr><tr><td>amountValue</td><td>decimal</td><td>The final amount charged to the user in the billing currency</td></tr><tr><td>amountCurrency</td><td>string</td><td>The ISO 4217 currency code for the charged amount (e.g., <code>PHP</code>)</td></tr><tr><td>originalValue</td><td>decimal</td><td>The original price of the item before any currency conversions</td></tr><tr><td>originalCurrency</td><td>string</td><td>The ISO 4217 currency code for the original price</td></tr><tr><td>resultCode</td><td>integer</td><td>Status code of the transaction. <code>0</code> indicates success; other values indicate errors.</td></tr><tr><td>resultDesc</td><td>string</td><td>A human-readable description of the transaction result.</td></tr><tr><td>shopper</td><td>object</td><td>An object containing shopper details such as ID, email, or partner-specific identifiers.</td></tr><tr><td>paymentMethod</td><td>object</td><td>Information regarding the payment instrument used (e.g., card type, last four digits).</td></tr><tr><td>transactionData</td><td>object</td><td>A flexible object containing supplementary metadata specific to the transaction or payment channel.</td></tr></tbody></table>

#### Successful Notification Example

```json
{
    "eventType": "CAPTURE_SUCCESSFUL",
    "txnId": 783437392732893567,
    "orderId": "2eb63b9e-f4c5-4e20-9783-2253cd7dc1d0",
    "checksum": "76c1eb25c01e4d5fd2fe8e64091b82bc",
    "chargedAt": "2026-04-01T00:00:00Z",
    "amountValue": 59.0,
    "amountCurrency": "PHP",
    "originalValue": 59.0,
    "originalCurrency": "PHP",
    "resultCode": 0,
    "resultDesc": "Success",
    "shopper": {},
    "paymentMethod": {},
    "transactionData": {}
}
```

#### Failed Notification Example

When an event like `AUTHORIZATION_FAILED` or `CAPTURE_FAILED` occurs, the `resultCode` will contain a non-zero value.

```json
{
    "eventType": "AUTHORIZATION_FAILED",
    "txnId": 783437392732893567,
    "orderId": "2eb63b9e-f4c5-4e20-9783-2253cd7dc1d0",
    "checksum": "76c1eb25c01e4d5fd2fe8e64091b82bc",
    "chargedAt": "2026-04-01T00:00:00Z",
    "amountValue": 59.0,
    "amountCurrency": "PHP",
    "originalValue": 59.0,
    "originalCurrency": "PHP",
    "resultCode": 750,
    "resultDesc": "Failed",
    "shopper": {},
    "paymentMethod": {},
    "transactionData": {}
  }
}
```

{% hint style="info" %}
You can find the full list of error codes and their meanings is available [here](/codapay/error-codes.md).
{% endhint %}

### Responding to Notifications

To acknowledge receipt of the notification, your server must respond with a `200 OK` and the following JSON body:

```json
{
  "ResultCode": 0
}
```

Retry Policy If no valid response is received, Codapay will re-send the notification 3 times at 5-minute intervals. If all attempts fail, an email alert will be triggered to your technical contact.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.coda.co/codapay/additional-features/saving-card-details-new-notification.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
