---
title: Send card payments
slug: tutorials/api/cos-card-payments/send-card-payments
description: Create a card token and send push or pull payments using COS Card Payments APIs.
docTags: 
createdAt: 2026-05-10T15:30:00.000Z
---

## What you will learn

✅ How to create a card token

✅ How to send a push payment (send funds to a card)

✅ How to send a pull payment (request funds from a card)

✅ How to test rejected scenarios

:::hint{type="info"}
If you are new to card payments, check out the [Card payments](docId\:y_2uVmzGOChmtEPEO4IPy)  overview.

This tutorial assumes familiarity with APIs. For more information, visit [API Basics](docId\:zg9CjGPbh9nMHCoit5W3a).
:::

This tutorial uses these API endpoints:

| API                                            | Description                                                       |
| ---------------------------------------------- | ----------------------------------------------------------------- |
| [Card tokens](docId\:CfF80NPHRpP3BUz2yCqRA)    | Creates a card token by validating the card with the card network |
| [Send payments](docId\:c6CjUrm0nl_nOY4oeJ8Gu)  | Sends a push or pull payment to or from a debit card              |
| [Payments by ID](docId:1XHjAplurDjMikKTX29_G)  | Retrieves payment details                                         |

## Before you begin

Make sure you have:

- [API credentials](docId\:Z-MVwOV-p00-xX082NabK)
- Your partner ID
- Your product ID
- An account number
- &#x20;[Register](docId\:gBUtUKMrauaj8DOQT8T2o) the following webhook events:

| Webhook                          | Description                                                 |
| -------------------------------- | ----------------------------------------------------------- |
| `CardPayments.Card.Approved`     | Card token authorization approved by the card network       |
| `CardPayments.Card.Rejected`     | Card token authorization rejected by the card network       |
| `CardPayments.Payment.Cleared`   | Payment passed hold evaluations and is being processed      |
| `CardPayments.Payment.Completed` | Payment transaction successfully completed                  |
| `CardPayments.Payment.Rejected`  | Payment transaction rejected by the issuing bank or network |
| `CardPayments.Payment.Failed`    | Payment failed to submit (validation error or system issue) |

You should be familiar with these terms:

| Term                 | Definition                                                                                         |
| -------------------- | -------------------------------------------------------------------------------------------------- |
| Card token           | A secure representation of a card number that can be used for transactions without storing the PAN |
| PAN                  | Primary Account Number - the full card number on the front of a debit card                         |
| Push payment         | Sending funds from your account to a cardholder's debit card                                       |
| Pull payment         | Requesting funds from a cardholder's debit card to your account                                    |
| Corresponding entity | Information about the sender (for push) or receiver (for pull) of funds                            |

## Create a card token

Before you can send a payment, you must create a card token. Card tokenization converts the cardholder's PAN (card number) into a secure token. Cross River validates the card with the card network. This confirms it can receive or send payments.

:::hint{type="info"}
Cross River does not store card numbers. Once tokenized, all future transactions use the token.
:::

In this tutorial, you will tokenize a test card for Alice Johnson. You can use [sample cards for testing](docId\:OJKIN15EzzTokXdlwB3Dn) in the sandbox environment.

:::::WorkflowBlock
::::WorkflowBlockItem
Call `POST /cardpayments/v1/cardtokens`.

For this call, these attributes are required:

| Attribute         | Description                                        |
| ----------------- | -------------------------------------------------- |
| `productId`       | Your unique product ID in COS                      |
| `accountNumber`   | The account number associated with this card token |
| `firstName`       | Cardholder's first name (1-35 characters)          |
| `lastName`        | Cardholder's last name (1-35 characters)           |
| `pan`             | The full card number                               |
| `expirationMonth` | Card expiration month (1-12)                       |
| `expirationYear`  | Card expiration year (4 digits)                    |

:::hint{type="warning"}
**IMPORTANT**

We strongly recommend that you include an [Idempotency](docId\:xQC2lRsG0xVv_9NMkqxKk) in the request header to prevent duplicate card tokens in case of a failure.
:::

:::hint{type="info"}
The `address` object is optional but recommended. When provided, the card network may perform address verification.
:::

:::CodeblockTabs
POST /cardpayments/v1/cardtokens request

```curl
POST /cardpayments/v1/cardtokens

{
  "productId": "31cae717-408e-4813-a6b1-ad6600e48632",
  "accountNumber": "2287979807",
  "clientIdentifier": "token-alice-001",
  "firstName": "Alice",
  "lastName": "Johnson",
  "address": {
    "street1": "456 Oak Avenue",
    "street2": "Apt 12B",
    "city": "Portland",
    "state": "OR",
    "postalCode": "97201",
    "countryCode": "US"
  },
  "phone": "5035551234",
  "emailAddress": "alice.johnson@example.com",
  "pan": "5102589999999905",
  "expirationMonth": 12,
  "expirationYear": 2028,
  "cvv": "123"
}
```
:::
::::

::::WorkflowBlockItem
A successful API call returns a JSON response containing the card token details.

Key attributes in the response:

- `id` - The unique card token ID
- `token` - The tokenized representation of the card (use this for payments)
- `authorizationStatus` - Either `Approved` or `Rejected`
- `capabilities` - Shows what payment types the card supports

:::CodeblockTabs
POST /cardpayments/v1/cardtokens response

```json
{
  "id": "26acd726-dade-4064-996a-b42b00b634df",
  "partnerId": "82a1cfb9-de92-4cc2-8a74-ad6600e36d7a",
  "productId": "31cae717-408e-4813-a6b1-ad6600e48632",
  "accountNumber": "2287979807",
  "token": "11FB445C487140A9BEA51457A796172A000000",
  "authorizationStatus": "Approved",
  "statusReasonCode": "00",
  "statusReasonDescription": "Approved and completed successfully",
  "isAuthorized": true,
  "firstName": "Alice",
  "lastName": "Johnson",
  "address": {
    "street1": "456 Oak Avenue",
    "street2": "Apt 12B",
    "city": "Portland",
    "state": "OR",
    "postalCode": "97201",
    "countryCode": "US"
  },
  "isAddressVerified": false,
  "accountNameInquiryUsed": "Used",
  "accountNameInquiryResult": "Match",
  "phone": "5035551234",
  "emailAddress": "alice.johnson@example.com",
  "binNumber": "510258",
  "panLastFour": "9905",
  "expirationMonth": 12,
  "expirationYear": 2028,
  "cardFingerprint": "7BleaDLyA+3nxDUkoX6WjE0GKUHvEniZuoJFFjVd0muNYH4P3VOoV0w5LX3JW4h75OMx50mIRTS6xnpcxLX/2w==",
  "isExpired": false,
  "cardBrand": "Mastercard",
  "capabilities": {
    "fastFundsSupported": true,
    "domesticPushEnabled": true,
    "domesticPullEnabled": true,
    "internationalPushEnabled": false,
    "internationalPullEnabled": false
  },
  "issuerCountryCode": "US",
  "clientIdentifier": "token-alice-001",
  "createdAt": "2026-05-10T15:30:23.6206088-04:00",
  "isActive": true,
  "authorizedAt": "2026-05-10T15:30:24.1757549-04:00",
  "lastModifiedAt": "2026-05-10T15:30:24.1757549-04:00"
}
```
:::

The `authorizationStatus` of `Approved` confirms that the card network validated this card. You can use it for payments. Check the `capabilities` object to see which payment types are supported.
::::

::::WorkflowBlockItem
The `CardPayments.Card.Approved` webhook event is triggered when the card network approves the card token.

:::CodeblockTabs
Sample CardPayments.Card.Approved event

```json
{
  "id": "7af80bc3-4f1c-4842-b60e-ad9400fb59db",
  "eventName": "CardPayments.Card.Approved",
  "status": "Pending",
  "partnerId": "82a1cfb9-de92-4cc2-8a74-ad6600e36d7a",
  "createdAt": "2026-05-10T15:30:24.623-04:00",
  "resources": [
    "cardpayments/v1/cardtokens/26acd726-dade-4064-996a-b42b00b634df"
  ],
  "details": {
    "cardId": "26acd726-dade-4064-996a-b42b00b634df",
    "clientIdentifier": "token-alice-001",
    "productId": "31cae717-408e-4813-a6b1-ad6600e48632",
    "cardBrand": "Mastercard",
    "panLastFour": "9905",
    "authorizationStatus": "Approved"
  }
}
```
:::
::::
:::::

## Send a push payment

Push payments send funds from your Cross River account to a cardholder's debit card. Funds typically reach the cardholder within minutes. Timing depends on the card network and issuing bank.

In this example, you will send $25.00 from your account to Alice Johnson's card.

:::::WorkflowBlock
::::WorkflowBlockItem
Call `POST /cardpayments/v1/payments`.

For this call, these attributes are required:

| Attribute       | Description                                                                    |
| --------------- | ------------------------------------------------------------------------------ |
| `accountNumber` | Your Cross River account number (funds will be debited from this account)      |
| `cardToken`     | The token from the card token creation response                                |
| `amount`        | The amount in cents (e.g., 2500 = $25.00)                                      |
| `paymentType`   | Set to `Push` for sending funds to a card                                      |
| `businessType`  | Two-character code indicating the transaction type (e.g., `P2P`, `B2C`, `B2B`) |

:::hint{type="info"}
Amounts are specified in cents without decimal points. For example, $25.00 is written as 2500.
:::

:::CodeblockTabs
POST /cardpayments/v1/payments request (push)

```curl
POST /cardpayments/v1/payments

{
  "productId": "31cae717-408e-4813-a6b1-ad6600e48632",
  "cardToken": "11FB445C487140A9BEA51457A796172A000000",
  "accountNumber": "2287979807",
  "amount": 2500,
  "paymentType": "Push",
  "correspondingEntity": {
    "firstName": "Alice",
    "lastName": "Johnson",
    "externalAccountIdentifier": "****9905",
    "address": {
      "street1": "456 Oak Avenue",
      "street2": "Apt 12B",
      "city": "Portland",
      "state": "OR",
      "postalCode": "97201",
      "countryCode": "US"
    }
  },
  "businessType": "P2P",
  "clientIdentifier": "payment-push-001"
}
```
:::
::::

::::WorkflowBlockItem
A successful API call returns a JSON response with the payment details.

The `status` attribute shows the current payment state. For a newly created payment, the status is typically `Created`.

:::CodeblockTabs
POST /cardpayments/v1/payments response (push)

```json
{
  "id": "d706c741-e556-4101-a849-b42b00bfd7e9",
  "clientIdentifier": "payment-push-001",
  "amount": 2500,
  "paymentType": "Push",
  "status": "Created",
  "source": "Api",
  "productId": "31cae717-408e-4813-a6b1-ad6600e48632",
  "partnerId": "82a1cfb9-de92-4cc2-8a74-ad6600e36d7a",
  "cardId": "26acd726-dade-4064-996a-b42b00b634df",
  "cardToken": "11FB445C487140A9BEA51457A796172A000000",
  "cardBrand": "Mastercard",
  "panLastFour": "9905",
  "issuerCountryCode": "US",
  "correspondingEntity": {
    "firstName": "Alice",
    "lastName": "Johnson",
    "externalAccountIdentifier": "****9905",
    "address": {
      "street1": "456 Oak Avenue",
      "street2": "Apt 12B",
      "city": "Portland",
      "state": "OR",
      "postalCode": "97201",
      "countryCode": "US"
    }
  },
  "accountNumber": "2287979807",
  "businessType": "P2P",
  "wasRefunded": false,
  "createdAt": "2026-05-10T15:35:28.8271201-04:00",
  "limitsEligibleOn": "2026-05-10T15:35:28.8271201-04:00",
  "lastModifiedAt": "2026-05-10T15:35:28.9388613-04:00"
}
```
:::

The `status` of `Created` indicates the payment was accepted and is being processed. The payment is not complete yet.
::::
:::::

### Push payment webhook flow

The payment goes through multiple stages, each triggering a webhook event:

:::::WorkflowBlock
::::WorkflowBlockItem
**Payment cleared**

The `CardPayments.Payment.Cleared` event fires when the payment passes internal hold evaluations. The system then submits it to the card network.

:::CodeblockTabs
Sample CardPayments.Payment.Cleared event

```json
{
  "id": "8c2a3b12-16c5-49db-84d8-b38a00fa1b2c",
  "eventName": "CardPayments.Payment.Cleared",
  "status": "Pending",
  "partnerId": "82a1cfb9-de92-4cc2-8a74-ad6600e36d7a",
  "createdAt": "2026-05-10T15:35:29.417-04:00",
  "resources": [
    "cardpayments/v1/payments/d706c741-e556-4101-a849-b42b00bfd7e9"
  ],
  "details": {
    "paymentId": "d706c741-e556-4101-a849-b42b00bfd7e9",
    "paymentType": "Push",
    "amount": "2500",
    "retrievalReferenceId": null,
    "traceNumber": null,
    "reasonCode": null,
    "reasonDescription": null,
    "clientIdentifier": "payment-push-001",
    "coreTransactionId": "18b8597a-393f-483d-9897-b42c00aa5788"
  }
}
```
:::
::::

::::WorkflowBlockItem
**Payment completed**

The `CardPayments.Payment.Completed` event fires when the payment is approved. This confirms the funds have been successfully transferred.

:::CodeblockTabs
Sample CardPayments.Payment.Completed event

```json
{
  "id": "9f3e5c67-9dd3-48e1-9488-b1720104c696",
  "eventName": "CardPayments.Payment.Completed",
  "status": "Pending",
  "partnerId": "82a1cfb9-de92-4cc2-8a74-ad6600e36d7a",
  "createdAt": "2026-05-10T15:35:32.150-04:00",
  "resources": [
    "cardpayments/v1/payments/d706c741-e556-4101-a849-b42b00bfd7e9"
  ],
  "details": {
    "paymentId": "d706c741-e556-4101-a849-b42b00bfd7e9",
    "paymentType": "Push",
    "amount": "2500",
    "retrievalReferenceId": "413715103005",
    "traceNumber": "103005",
    "reasonCode": "00",
    "reasonDescription": "Approved",
    "clientIdentifier": "payment-push-001",
    "coreTransactionId": "18b8597a-393f-483d-9897-b42c00aa5788"
  }
}
```
:::

The `reasonCode` of `00` and `reasonDescription` of `Approved` confirm the payment was successful.
::::
:::::

## Send a pull payment

Pull payments request funds from a cardholder's debit card to your Cross River account. This is commonly used for collecting payments from customers.

In this example, you will request $15.50 from Alice Johnson's card.

:::::WorkflowBlock
::::WorkflowBlockItem
Call `POST /cardpayments/v1/payments`.

The request is nearly identical to a push payment, except:

- Set `paymentType` to `Pull`
- The `correspondingEntity` represents the payer (the person whose card is being charged)

:::CodeblockTabs
POST /cardpayments/v1/payments request (pull)

```curl
POST /cardpayments/v1/payments

{
  "productId": "31cae717-408e-4813-a6b1-ad6600e48632",
  "cardToken": "11FB445C487140A9BEA51457A796172A000000",
  "accountNumber": "2287979807",
  "amount": 1550,
  "paymentType": "Pull",
  "correspondingEntity": {
    "firstName": "Alice",
    "lastName": "Johnson",
    "externalAccountIdentifier": "****9905",
    "address": {
      "street1": "456 Oak Avenue",
      "street2": "Apt 12B",
      "city": "Portland",
      "state": "OR",
      "postalCode": "97201",
      "countryCode": "US"
    }
  },
  "businessType": "P2P",
  "clientIdentifier": "payment-pull-001"
}
```
:::
::::

::::WorkflowBlockItem
The response structure is the same as push payments, with `paymentType` set to `Pull`.

:::CodeblockTabs
POST /cardpayments/v1/payments response (pull)

```json
{
  "id": "f8c4d823-7a21-4956-b7e2-c93b01aef4d2",
  "clientIdentifier": "payment-pull-001",
  "amount": 1550,
  "paymentType": "Pull",
  "status": "Created",
  "source": "Api",
  "productId": "31cae717-408e-4813-a6b1-ad6600e48632",
  "partnerId": "82a1cfb9-de92-4cc2-8a74-ad6600e36d7a",
  "cardId": "26acd726-dade-4064-996a-b42b00b634df",
  "cardToken": "11FB445C487140A9BEA51457A796172A000000",
  "cardBrand": "Mastercard",
  "panLastFour": "9905",
  "issuerCountryCode": "US",
  "correspondingEntity": {
    "firstName": "Alice",
    "lastName": "Johnson",
    "externalAccountIdentifier": "****9905",
    "address": {
      "street1": "456 Oak Avenue",
      "street2": "Apt 12B",
      "city": "Portland",
      "state": "OR",
      "postalCode": "97201",
      "countryCode": "US"
    }
  },
  "accountNumber": "2287979807",
  "businessType": "P2P",
  "wasRefunded": false,
  "createdAt": "2026-05-10T15:40:15.2134567-04:00",
  "limitsEligibleOn": "2026-05-10T15:40:15.2134567-04:00",
  "lastModifiedAt": "2026-05-10T15:40:15.3245678-04:00"
}
```
:::
::::
:::::

Pull payments follow the same webhook flow as push payments (Cleared → Completed), with the same event structure.

## Test rejected scenarios

You can test various rejection scenarios in the sandbox environment to understand how your application should handle failures.

### Simulate rejected card authorization

To test a card token rejection, use a test card number that triggers a specific rejection response.

:::::WorkflowBlock
::::WorkflowBlockItem
Call `POST /cardpayments/v1/cardtokens` using a test card that will be rejected.

Use the Visa test card `4000289999999906` which simulates a card that fails authorization checks.

:::CodeblockTabs
POST /cardpayments/v1/cardtokens request (rejected)

```curl
POST /cardpayments/v1/cardtokens

{
  "productId": "31cae717-408e-4813-a6b1-ad6600e48632",
  "accountNumber": "2287979807",
  "firstName": "Test",
  "lastName": "Reject",
  "address": {
    "street1": "123 Test Street",
    "city": "New York",
    "state": "NY",
    "postalCode": "10001",
    "countryCode": "US"
  },
  "pan": "4000289999999906",
  "expirationMonth": 12,
  "expirationYear": 2028,
  "cvv": "123"
}
```
:::
::::

::::WorkflowBlockItem
The response shows `authorizationStatus` of `Rejected`.

:::CodeblockTabs
POST /cardpayments/v1/cardtokens response (rejected)

```json
{
  "id": "ee7870ba-5ef7-4700-92ed-bed8a77abe7c",
  "partnerId": "82a1cfb9-de92-4cc2-8a74-ad6600e36d7a",
  "productId": "31cae717-408e-4813-a6b1-ad6600e48632",
  "accountNumber": "2287979807",
  "token": null,
  "authorizationStatus": "Rejected",
  "statusReasonCode": "14",
  "statusReasonDescription": "Invalid card number",
  "isAuthorized": false,
  "firstName": "Test",
  "lastName": "Reject",
  "panLastFour": "9906",
  "cardBrand": "Visa",
  "isActive": false,
  "createdAt": "2026-05-10T15:45:23.6206088-04:00"
}
```
:::
::::

::::WorkflowBlockItem
The `CardPayments.Card.Rejected` webhook event is triggered.

:::CodeblockTabs
Sample CardPayments.Card.Rejected event

```json
{
  "id": "3c8f6a21-dc90-48ea-b642-b04a0126580f",
  "eventName": "CardPayments.Card.Rejected",
  "status": "Pending",
  "partnerId": "82a1cfb9-de92-4cc2-8a74-ad6600e36d7a",
  "createdAt": "2026-05-10T15:45:24.417-04:00",
  "resources": [
    "cardpayments/v1/cardtokens/ee7870ba-5ef7-4700-92ed-bed8a77abe7c"
  ],
  "details": {
    "cardId": "ee7870ba-5ef7-4700-92ed-bed8a77abe7c",
    "clientIdentifier": null,
    "productId": "31cae717-408e-4813-a6b1-ad6600e48632",
    "cardBrand": "Visa",
    "panLastFour": "9906",
    "authorizationStatus": "Rejected"
  }
}
```
:::
::::
:::::

### Simulate rejected payment

To test a payment rejection (after successful card tokenization), provide invalid or missing required data.

:::::WorkflowBlock
::::WorkflowBlockItem
Call `POST /cardpayments/v1/payments` with missing required fields in the `correspondingEntity` object.

:::CodeblockTabs
POST /cardpayments/v1/payments request (rejected)

```curl
POST /cardpayments/v1/payments

{
  "productId": "31cae717-408e-4813-a6b1-ad6600e48632",
  "cardToken": "11FB445C487140A9BEA51457A796172A000000",
  "accountNumber": "2287979807",
  "amount": 1000,
  "paymentType": "Push",
  "correspondingEntity": {
    "firstName": "Alice",
    "lastName": "Johnson"
  },
  "businessType": "P2P"
}
```
:::
::::

::::WorkflowBlockItem
The `CardPayments.Payment.Failed` event fires when the payment fails validation.

:::CodeblockTabs
Sample CardPayments.Payment.Failed event

```json
{
  "id": "eb8f80f8-6e1c-428f-be54-b1720103ea5d",
  "eventName": "CardPayments.Payment.Failed",
  "status": "Pending",
  "partnerId": "82a1cfb9-de92-4cc2-8a74-ad6600e36d7a",
  "createdAt": "2026-05-10T15:50:18.603-04:00",
  "resources": [
    "cardpayments/v1/payments/eb8f80f8-6e1c-428f-be54-b1720103ea5d"
  ],
  "details": {
    "paymentId": "eb8f80f8-6e1c-428f-be54-b1720103ea5d",
    "paymentType": "Push",
    "amount": "1000",
    "retrievalReferenceId": null,
    "traceNumber": null,
    "reasonCode": "1000",
    "reasonDescription": "AddressLine1 for corresponding entity is required.",
    "clientIdentifier": null,
    "coreTransactionId": null
  }
}
```
:::

The `reasonCode` and `reasonDescription` provide details about why the payment failed.
::::
:::::

## Verify payment status

You can retrieve the current status of any payment at any time.

:::::WorkflowBlock
:::WorkflowBlockItem
Call `GET /cardpayments/v1/payments/{id}` using the payment ID from the response.

```curl
GET /cardpayments/v1/payments/d706c741-e556-4101-a849-b42b00bfd7e9
```
:::

::::WorkflowBlockItem
The response includes the current payment status and all transaction details.

:::CodeblockTabs
GET /cardpayments/v1/payments/\{id} response

```json
{
  "id": "d706c741-e556-4101-a849-b42b00bfd7e9",
  "clientIdentifier": "payment-push-001",
  "amount": 2500,
  "paymentType": "Push",
  "status": "Completed",
  "source": "Api",
  "productId": "31cae717-408e-4813-a6b1-ad6600e48632",
  "partnerId": "82a1cfb9-de92-4cc2-8a74-ad6600e36d7a",
  "cardId": "26acd726-dade-4064-996a-b42b00b634df",
  "cardToken": "11FB445C487140A9BEA51457A796172A000000",
  "cardBrand": "Mastercard",
  "panLastFour": "9905",
  "retrievalReferenceId": "413715103005",
  "traceNumber": "103005",
  "statusReasonCode": "00",
  "statusReasonDescription": "Approved",
  "issuerCountryCode": "US",
  "correspondingEntity": {
    "firstName": "Alice",
    "lastName": "Johnson",
    "externalAccountIdentifier": "****9905",
    "address": {
      "street1": "456 Oak Avenue",
      "street2": "Apt 12B",
      "city": "Portland",
      "state": "OR",
      "postalCode": "97201",
      "countryCode": "US"
    }
  },
  "accountNumber": "2287979807",
  "businessType": "P2P",
  "wasRefunded": false,
  "createdAt": "2026-05-10T15:35:28.8271201-04:00",
  "completedAt": "2026-05-10T15:35:32.4567890-04:00",
  "limitsEligibleOn": "2026-05-10T15:35:28.8271201-04:00",
  "lastModifiedAt": "2026-05-10T15:35:32.4567890-04:00"
}
```
:::

The `status` of `Completed` and `completedAt` timestamp confirm the payment successfully processed.
::::
:::::

