---
description: >-
  Authorize a card payment by submitting a tokenized card to the /v2/payment
  endpoint. Supports pre-authorization and direct capture.
---

# Authorizing a Card Payment

After [tokenizing a card](../../../../tokenizing-cards.md), submit the token to create a payment authorization. You can choose between:

- **Pre-authorization** (`"capture": false`) — Reserves funds without settling. You capture later when ready.
- **Direct capture** (`"capture": true`) — Authorizes and captures in one step. Funds are settled immediately.

---

## Understanding Pre-Authorization vs. Direct Capture

This is one of the most commonly misunderstood concepts in card payments. Getting it right determines how much control you have over your money flow — and how quickly you can reverse a transaction if something goes wrong.

### What is pre-authorization?

When you set `"capture": false`, the gateway asks the cardholder's bank to **reserve** the funds on their card — but **no money moves yet**. The cardholder sees a "pending" charge on their statement, but settlement (the actual transfer of funds to your account) does not happen until you explicitly [capture](../capture.md) the payment.

Think of it as placing a hold on the funds. The money is still in the cardholder's account, but they can't spend it elsewhere.

### Why use pre-authorization?

Pre-authorization gives you a window to perform additional checks **before** committing to the financial settlement:

- **AVS / CVC verification** — Review the address and security code results from the authorization response. If they indicate fraud risk, you can cancel immediately.
- **Anti-fraud analysis** — Run the transaction through your fraud scoring system, manual review queues, or third-party fraud tools.
- **Inventory / fulfillment checks** — Confirm the item is in stock, the service is available, or any business-specific validation passes.
- **Compliance / KYC** — Verify the customer meets regulatory requirements before finalizing the transaction.
- **Order adjustments** — The final amount may differ from the initial hold (e.g., partial shipments). You can capture a smaller amount than authorized.

### The key advantage: fast, clean reversal

If you need to cancel a pre-authorized transaction, you perform a [**void**](../void.md). A void **instantly releases** the hold on the cardholder's funds — typically within minutes. The cardholder sees the pending charge disappear from their statement. No money was ever moved, so there's nothing to "return."

Compare this to what happens after capture: once a transaction is captured, settlement has occurred. The money has left the cardholder's account and landed in yours. The **only** way to return funds at that point is a [**refund**](../refund.md), which is a separate financial transaction that can take **3–10 business days** to appear on the cardholder's statement.

### Side-by-side comparison

| | Pre-authorization (`capture: false`) | Direct capture (`capture: true`) |
|---|---|---|
| **What happens** | Funds are held (reserved) on the card | Funds are held AND settled immediately |
| **Money moves?** | ❌ No — just a hold | ✅ Yes — settlement begins |
| **To cancel** | **Void** — instant, no money moved | **Refund** — separate transaction, 3–10 days |
| **Cardholder sees** | "Pending" charge | Completed charge |
| **Time limit** | Must capture within **7 days** or the hold expires automatically | N/A — already captured |
| **Can adjust amount?** | ✅ Capture less than authorized | ❌ Amount is final |
| **Best for** | E-commerce, travel, subscriptions, anything needing review | Simple point-of-sale, instant digital goods |

### When to use which

**Use pre-authorization (`capture: false`) when:**
- You need time to verify fraud signals, AVS/CVC results, or compliance
- The final amount might change (partial shipments, tips, hotel incidentals)
- You want the ability to cancel cleanly without a refund hitting the cardholder's statement
- Your fulfillment has any delay between payment and delivery

**Use direct capture (`capture: true`) when:**
- The transaction is final and immediate (digital download, in-store purchase)
- No review or adjustment is needed
- You want the simplest integration with fewer API calls

### The lifecycle at a glance

```
                 capture: false                    capture: true
                 ─────────────                     ─────────────
POST /v2/payment                          POST /v2/payment
       │                                         │
       ▼                                         ▼
   AUTHORIZED                                CAPTURED
   (funds held)                              (funds settled)
       │                                         │
   ┌───┴───┐                                     ▼
   │       │                                  REFUNDED
   ▼       ▼                               (3-10 days to
CAPTURED  VOIDED                            cardholder)
(settle)  (release hold,
   │       instant)
   ▼
REFUNDED
(3-10 days)
```

> **Bottom line:** If there's any chance you might need to cancel the transaction after authorization, use pre-authorization. It's faster to reverse, cleaner for the cardholder, and gives you full control over the settlement timing.

---

## Endpoint

```
POST https://sandbox-gw.simpleps.com/v2/payment
```

**Headers:**

| Header | Value |
|---|---|
| `Authorization` | `Bearer {accessToken}` |
| `Content-Type` | `application/json` |

## Request Body

### Root Object

| Field | Type | Required | Description |
|---|---|---|---|
| `externalPaymentId` | string | ✅ | Your unique identifier for this payment (idempotency key) |
| `ipAddress` | string | ✅ | Payer's IPv4 or IPv6 address |
| `paymentType` | string | ✅ | `"PULL"` |
| `capture` | boolean | ✅ | `true` = auto-capture; `false` = pre-auth only |
| `amount` | object | ✅ | Transaction amount |
| `sender` | object | ✅ | Payer details |

### `amount` Object

| Field | Type | Required | Description |
|---|---|---|---|
| `total` | number | ✅ | Amount to charge (must be ≥ 1) |
| `currency` | string | ✅ | ISO 4217 currency code (e.g., `"USD"`) |

### `sender` Object

| Field | Type | Required | Description |
|---|---|---|---|
| `firstName` | string | ✅ | Payer's first name |
| `lastName` | string | ✅ | Payer's last name |
| `address` | object | ✅ | Billing address (used for AVS verification) |
| `paymentMethod` | object | ✅ | Card token details |

### `sender.address` Object

| Field | Type | Required | Description |
|---|---|---|---|
| `countryCode` | string | ✅ | ISO Alpha-3 country code (e.g., `"USA"`) |
| `stateCode` | string | ✅ | State/province abbreviation (e.g., `"NY"`) |
| `city` | string | ✅ | City name |
| `line1` | string | ✅ | Street address line 1 |
| `line2` | string | ❌ | Street address line 2 |
| `zipCode` | string | ✅ | Postal/ZIP code |

### `sender.paymentMethod` Object (Card)

| Field | Type | Required | Description |
|---|---|---|---|
| `type` | string | ✅ | `"CARD"` |
| `cardTokenId` | string | ✅ | Token UUID from the tokenizer |
| `previousPaymentId` | string | ❌ | Required for recurring tokens — the `paymentId` from the initial authorization |

## Example Request

```bash
curl -X POST https://sandbox-gw.simpleps.com/v2/payment \
  -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIs...' \
  -H 'Content-Type: application/json' \
  -d '{
    "externalPaymentId": "order-12345",
    "ipAddress": "203.0.113.42",
    "paymentType": "PULL",
    "capture": false,
    "amount": {
      "total": 99.99,
      "currency": "USD"
    },
    "sender": {
      "firstName": "John",
      "lastName": "Smith",
      "address": {
        "countryCode": "US",
        "stateCode": "NY",
        "city": "New York",
        "line1": "123 Main Street",
        "line2": "Apt 4B",
        "zipCode": "10001"
      },
      "paymentMethod": {
        "type": "CARD",
        "cardTokenId": "ab5fc589-8b48-4531-94c0-68b0629c13fe"
      }
    }
  }'
```

## Response

### Successful Authorization (200)

```json
{
  "status": 200,
  "data": {
    "paymentId": "dce568c6-98ec-456c-bb33-4a6809c4fff8",
    "parentPaymentId": "dce568c6-98ec-456c-bb33-4a6809c4fff8",
    "externalPaymentId": "order-12345",
    "amount": 99.99,
    "created": "2025-03-31 03:49:05",
    "approved": true,
    "message": "Payment Approved",
    "automaticReversed": false,
    "status": "AUTHORIZED",
    "captured": false,
    "voided": false,
    "responseCode": "00",
    "issuerName": "BANK OF AMERICA",
    "issuerCountry": "UNITED STATES",
    "cvcResult": "APPROVED",
    "avsResult": "APPROVED",
    "avsCardholderNameResult": "N/A",
    "avsTelephoneResult": "N/A"
  }
}
```

### 3DS Challenge Required (200)

When the issuing bank requires cardholder verification, the response returns `status: "CHALLENGE"` with a `redirectAcsUrl`:

```json
{
  "status": 200,
  "data": {
    "paymentId": "dce568c6-98ec-456c-bb33-4a6809c4fff8",
    "externalPaymentId": "order-12345",
    "redirectAcsUrl": "https://sandbox-gw.simpleps.com/secure-code/start-challenge?token=dce568c6-...",
    "amount": 99.99,
    "approved": false,
    "message": "Payment awaiting 3DS challenge verification",
    "status": "CHALLENGE",
    "captured": false,
    "voided": false,
    "responseCode": "00",
    "cvcResult": "N/A",
    "avsResult": "N/A"
  }
}
```

When you receive `CHALLENGE`, redirect the cardholder to `redirectAcsUrl`. See [Handling 3D Secure](handling-3d-secure.md) for the complete flow.

### Declined (400)

```json
{
  "status": 400,
  "data": {
    "paymentId": "abc12345-...",
    "externalPaymentId": "order-12345",
    "amount": 99.99,
    "approved": false,
    "message": "Not sufficient funds",
    "status": "DECLINED",
    "responseCode": "PAY_084"
  }
}
```

## Response Fields

| Field | Type | Description |
|---|---|---|
| `paymentId` | string | Inyo's unique payment identifier |
| `parentPaymentId` | string | Parent payment ID (same as `paymentId` for initial authorizations) |
| `externalPaymentId` | string | Your original external ID |
| `redirectAcsUrl` | string | 3DS challenge URL (only present when `status` = `CHALLENGE`) |
| `amount` | number | Transaction amount |
| `created` | string | Timestamp (EST) |
| `approved` | boolean | `true` if authorized successfully |
| `message` | string | Human-readable status message |
| `automaticReversed` | boolean | `true` if payment was auto-reversed by fraud rules |
| `status` | string | `AUTHORIZED`, `CHALLENGE`, or `DECLINED` |
| `captured` | boolean | `true` if auto-captured (`"capture": true` in request) |
| `voided` | boolean | `true` if voided |
| `responseCode` | string | Issuer/gateway response code (see [Response Codes](../../../../domain-tables/response-code.md)) |
| `issuerName` | string | Name of the issuing bank |
| `issuerCountry` | string | Country of the issuer |
| `cvcResult` | string | `APPROVED`, `FAILED`, `NOT_SENT`, or `N/A` |
| `avsResult` | string | `APPROVED`, `FAILED`, `NOT_SENT`, or `N/A` |

## Using a Recurring Token

If the card was tokenized with `storeLaterUse: true`, you can reuse the token for future charges by including the `previousPaymentId`:

```json
{
  "sender": {
    "paymentMethod": {
      "type": "CARD",
      "cardTokenId": "ab5fc589-8b48-4531-94c0-68b0629c13fe",
      "previousPaymentId": "dce568c6-98ec-456c-bb33-4a6809c4fff8"
    }
  }
}
```

## What's Next

- **Authorized?** → [Capture](../capture.md) the payment when ready to settle
- **Need to cancel?** → [Void](../void.md) the authorization before capture
- **3DS Challenge?** → [Handle 3D Secure](handling-3d-secure.md) redirect flow
- **Check verification?** → [AVS / CVC results](handling-avs-cvc.md)
