# Card Payments

To use this capability, add `octo/cardPayments` to your `Octo-Capabilities` header.

This capability allows you to accept card payments via the API.

Gateway IDs returned/accepted in source are:

* `adyen`
* `external`

## Endpoints

All paths below are under `/octo`.

This capability extends booking/order/gift write flows and related read flows documented in:

* [Bookings](/octo-core/bookings.md#endpoints)
* [Multi-Booking Cart](/capabilities/cart.md)
* [Gift Vouchers](/capabilities/gift-vouchers.md)

List routes intentionally omit `cardPayment`/`returnUrl`.

{% openapi src="/files/9aBZzqykFPaTU7bfbNrr" path="/card\_payments/{cardPaymentId}" method="get" %}
[openapi.yaml](https://221588849-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M7bgGIyO7QYNOfUMfxh%2Fuploads%2Fgit-blob-fa2d8cb1d7297d352c2639e6c4c6a990f2add6d7%2Fopenapi.yaml?alt=media)
{% endopenapi %}

Validation rules from source:

* `cardPayment.source` must be one of `POS`, `ECOM`, `MOTO` (`GATEWAY_INVALID_SOURCE` otherwise).
* `cardPayment.currency` must match the order currency (`GATEWAY_CURRENCY_MISMATCH` otherwise).
* If `cardPayment.cardId` is supplied it must reference a reusable card on the selected gateway (`INVALID_CARD_ID` otherwise).
* If an explicit gateway is supplied and does not match the resolved gateway, source raises `GATEWAY_MISMATCH`.

## Response Fields

All card payment request/response fields (including `reusableCards[]` and gateway payloads) are included on the card payment schemas in this page.

Notes:

* `adyen` can return `{}` when `amount <= 0`.
* The card payment lookup endpoint returns cached card payment JSON (up to 1 hour) and is only available when the card payment object was created with a `returnUrl`.

## Adyen Gateway

{% embed url="<https://docs.adyen.com/online-payments/build-your-integration?platform=Web&integration=Drop-in&version=5.43.0>" %}
Adyen Drop-in Integration Docs
{% endembed %}

`session` is `null` until you set a `returnUrl` (for `ECOM` payments).

When you confirm/replay payment, source accepts:

* `adyen.sessionId`
* `adyen.sessionResult` (optional with sessionId)
* `adyen.pspReference`
* `adyen.paymentMethod`
* `adyen.channel`

For Adyen session creation, channel is resolved from the `adyen-channel` request header first, then `cardPayment.adyen.channel`, then defaults to `Web`.

Most integrations send this payload on the booking/order/gift confirm route that finalizes payment.

If Ventrata has not yet received the webhook notification from Adyen then you may receive a `PAYMENT_PENDING` error code. Repeat the request. If the payment is refused, you get a `BAD_REQUEST` error with the reason in `errorMessage`.

## External Gateway

The external gateway lets you register a virtual card payment taken on an external processor.

`external.approved` defaults to `true` when omitted. For external payload processing, source requires at least one of `notes`, `amount`, `currency`, or `cancel` to be present.

## Reusable Cards

Reusable card fields are included in the `ReusableCard` schema.

## Schema Additions (JSON)

These are additive fragments showing only fields introduced by this capability.

### `Booking`

```json
{
  "// ...rest of booking object": "...",
  "cardPayment": {
    "status": "CONFIRMED",
    "id": "3d6f0a3a-59d4-4b16-a0c5-11d2d8a4e6b7",
    "cardPaymentId": "cp_20260514_42ad10",
    "gateway": "adyen",
    "source": "POS",
    "paid": 2200,
    "totalPaid": 2200,
    "totalRefunded": 0,
    "paidSurcharge": 0,
    "balance": 0,
    "surcharge": 0,
    "outstandingBalance": 0,
    "amount": 2200,
    "currency": "USD",
    "currencyPrecision": 2,
    "reusableCards": [
      {
        "id": "e7cc8bb4-8d1c-4848-8824-5dbedb718681",
        "brand": "visa",
        "bin": "411111",
        "last4": "1111"
      }
    ],
    "adyen": {
      "environment": "test",
      "clientKey": "test_client_key_123",
      "session": {
        "id": "e7cc8bb4-8d1c-4848-8824-5dbedb718681",
        "sessionData": "session_data_payload"
      },
      "countryCode": "US"
    },
    "external": {},
    "provider": "adyen",
    "providerReference": "PROV-REF-2026-001",
    "createdAt": "2026-05-14T13:00:00Z"
  },
  "returnUrl": "https://checkout.city-sightseeing.com/return"
}
```

### `BookingWriteRequest`

```json
{
  "// ...rest of booking write request object": "...",
  "cardPayment": {
    "gateway": "adyen"
  },
  "returnUrl": "https://checkout.city-sightseeing.com/return"
}
```

### `Error`

```json
{
  "// ...rest of error object": "...",
  "cardPaymentId": "cp_20260514_42ad10"
}
```

### `Gift`

```json
{
  "// ...rest of gift object": "...",
  "cardPayment": {
    "id": "f1a5d2e8-8d57-4f0b-9c3f-6a12d7a8bc90",
    "gateway": "external",
    "status": "PENDING"
  },
  "returnUrl": "https://checkout.city-sightseeing.com/return"
}
```

### `GiftCreateRequest`

```json
{
  "// ...rest of gift create request object": "...",
  "cardPayment": {
    "gateway": "external",
    "external": {
      "approved": true
    }
  },
  "returnUrl": "https://checkout.city-sightseeing.com/return"
}
```

### `Order`

```json
{
  "// ...rest of order object": "...",
  "cardPayment": {
    "id": "f1a5d2e8-8d57-4f0b-9c3f-6a12d7a8bc90",
    "gateway": "adyen",
    "status": "PENDING"
  },
  "returnUrl": "https://checkout.city-sightseeing.com/return"
}
```

### `OrderCreateRequest`

```json
{
  "// ...rest of order create request object": "...",
  "cardPayment": {
    "gateway": "adyen"
  },
  "returnUrl": "https://checkout.city-sightseeing.com/return"
}
```

### `OrderUpdateRequest`

```json
{
  "// ...rest of order update request object": "...",
  "cardPayment": {
    "gateway": "adyen"
  },
  "returnUrl": "https://checkout.city-sightseeing.com/return"
}
```


---

# Agent Instructions: 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:

```
GET https://docs.ventrata.com/capabilities/card-payments.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
