> For the complete documentation index, see [llms.txt](https://firstoken.gitbook.io/api-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://firstoken.gitbook.io/api-docs/api-reference/payments/payments-api-koin/payments-complete-flow.md).

# Payments - Complete Flow

### Overview

The Payments endpoint processes a complete payment transaction with automatic tokenization, authorization, and capture in a single API call. This is the most common endpoint for direct sales where you want immediate payment collection.

**POST** `/v1/payments/`

### What Happens Internally

```
Client Request → Firstoken API → [Tokenization + Authorization + Capture] → Response
```

1. **Tokenization**: Card data is securely tokenized
2. **Authorization**: Payment is authorized with the token
3. **Capture**: Payment is automatically captured
4. **Response**: Single response with the complete transaction result

### Request Body

#### Minimal Required Fields

```json
{
  "transaction_info": {
    "type": "payment",
    "reference_code": "1753550023570"
  },
  "card": {
    "number": "4225289837059229",
    "expiration_date": "01/2030",
    "security_code": "123",
    "holder": "John Doe Jones"
  },
  "order_info": {
    "amount_details": {
      "total_amount": 1000,
      "currency": "BRL",
      "items_amount": 1000
    },
    "installments": 1,
    "descriptor": "Test Payment"
  },
  "cardholder_info": {
    "first_name": "John",
    "last_name": "Doe",
    "document": {
      "type": "CPF",
      "number": "54672396002",
      "nationality": "BR"
    },
    "country": "BR",
    "address_1": "123 Main St",
    "city": "Sao Paulo",
    "state": "SP",
    "postal_code": "04001-000",
    "email": "john_autoaccept@test.com",
    "phone_number": "4158880000",
    "phone_type": "Mobile",
    "phone_area_code": "22"
  },
  "bill_to": {
    "id": "1234567890",
    "first_name": "John",
    "last_name": "Doe",
    "document": {
      "type": "CPF",
      "number": "54672396002",
      "nationality": "BR"
    },
    "country": "BR",
    "address_1": "123 Main St",
    "city": "Sao Paulo",
    "state": "SP",
    "postal_code": "04001-000",
    "email": "test@cybs.com",
    "phone_number": "4158880000",
    "phone_type": "Mobile",
    "phone_area_code": "22",
    "profile": "1"
  },
  "line_items": [
    {
      "category": {
        "id": "1",
        "name": "Category 1"
      },
      "id": "1",
      "name": "Item 1",
      "price": 1500,
      "quantity": 1,
      "type": "Generic"
    }
  ],
  "device_info": {
    "fingerprint_session_id": "0a76c25669713d8d6d306ba8c21259b7",
    "ip_address": "127.0.0.1"
  }
}
```

#### Complete Request with All Fields

```json
{
  "transaction_info": {
    "type": "payment",
    "reference_code": "1753550698549"
  },
  "card": {
    "number": "4225289837059229",
    "expiration_date": "01/2030",
    "security_code": "123",
    "holder": "John Doe Jones"
  },
  "order_info": {
    "amount_details": {
      "total_amount": 1000,
      "currency": "BRL",
      "items_amount": 1000,
      "shipping_amount": 20,
      "fee_amount": 10
    },
    "installments": 1,
    "descriptor": "Test Payment"
  },
  "cardholder_info": {
    "first_name": "John",
    "last_name": "Doe",
    "document": {
      "type": "CPF",
      "number": "54672396002",
      "nationality": "BR"
    },
    "gender": "MALE",
    "country": "BR",
    "address_1": "123 Main St",
    "address_2": "address 2",
    "city": "Sao Paulo",
    "state": "SP",
    "postal_code": "04001-000",
    "birth_date": "2025-07-01",
    "email": "john_autoaccept@test.com",
    "phone_number": "4158880000",
    "phone_type": "Mobile",
    "phone_country_code": "58",
    "phone_area_code": "22"
  },
  "bill_to": {
    "id": "1234567890",
    "first_name": "John",
    "last_name": "Doe",
    "document": {
      "type": "CPF",
      "number": "54672396002",
      "nationality": "BR"
    },
    "gender": "MALE",
    "country": "BR",
    "address_1": "123 Main St",
    "address_2": "address 2",
    "city": "Sao Paulo",
    "state": "SP",
    "postal_code": "04001-000",
    "birth_date": "2025-07-01",
    "email": "test@cybs.com",
    "phone_number": "4158880000",
    "phone_type": "Mobile",
    "phone_area_code": "22",
    "profile": "1"
  },
  "line_items": [
    {
      "category": {
        "id": "1",
        "name": "Category 1"
      },
      "discount_amount": 10,
      "id": "1",
      "name": "Item 1",
      "price": 1500,
      "quantity": 1,
      "seller_id": "seller id",
      "service_date": "2025-07-01",
      "type": "Generic"
    }
  ],
  "shipping_info": {
    "country": "BR",
    "address_1": "123 Main St",
    "address_2": "address 2",
    "city": "Sao Paulo",
    "state": "SP",
    "postal_code": "04001-000",
    "by": "DHL",
    "date": "2021-01-01T00:00:00.000Z",
    "type": "EXPRESS",
    "price": 1000
  },
  "device_info": {
    "ip_address": "127.0.0.1",
    "fingerprint_session_id": "0a76c25669713d8d6d306ba8c21259b7",
  }
}
```

### Field Specifications

#### transaction\_info (Required)

| Field            | Type   | Required | Description             |
| ---------------- | ------ | -------- | ----------------------- |
| `type`           | String | Yes      | Must be "payment"       |
| `reference_code` | String | Yes      | Merchant reference code |

#### card (Required)

| Field             | Type   | Required | Description                           |
| ----------------- | ------ | -------- | ------------------------------------- |
| `number`          | String | Yes      | Card number                           |
| `expiration_date` | String | Yes      | Card expiration (MM/YYYY format)      |
| `security_code`   | String | Yes      | CVV/CVC code (3-4 digits)             |
| `holder`          | String | Yes      | Cardholder name as it appears on card |

{% hint style="warning" %}

#### Note: Use a Firstoken token instead of card details; simply apply the token directly as follow

* Temporal token:&#x20;

  ```postman_json
  "{{08d40297-29d3-493e-b790-8e1085bc0a11: transaction}}"
  ```
* Permanent token (you can use all schema token types) :

  ```postman_json
  "{{419894dd-4211-409b-a31e-c76aba8da9f3: detokenize}}"
  ```

{% endhint %}

#### order\_info (Required)

| Field                            | Type   | Required | Description                    |
| -------------------------------- | ------ | -------- | ------------------------------ |
| `amount_details.total_amount`    | Number | Yes      | Total transaction amount       |
| `amount_details.currency`        | String | Yes      | Currency code (BRL, USD, etc.) |
| `amount_details.items_amount`    | Number | Yes      | Sum of line items amount       |
| `amount_details.shipping_amount` | Number | No       | Shipping cost                  |
| `amount_details.fee_amount`      | Number | No       | Additional fees                |
| `installments`                   | Number | Yes      | Number of installments         |
| `descriptor`                     | String | Yes      | Payment descriptor             |

#### cardholder\_info (Required)

| Field                  | Type   | Required | Description                     |
| ---------------------- | ------ | -------- | ------------------------------- |
| `first_name`           | String | Yes      | First name                      |
| `last_name`            | String | Yes      | Last name                       |
| `document.type`        | String | Yes      | Document type (CPF, CNPJ)       |
| `document.number`      | String | Yes      | Document number                 |
| `document.nationality` | String | Yes      | Document nationality (BR)       |
| `country`              | String | Yes      | Country code                    |
| `address_1`            | String | Yes      | Primary address                 |
| `city`                 | String | Yes      | City name                       |
| `state`                | String | Yes      | State code                      |
| `postal_code`          | String | Yes      | Postal code                     |
| `email`                | String | Yes      | Email address                   |
| `phone_number`         | String | Yes      | Phone number                    |
| `phone_type`           | String | No       | Phone type (Mobile, Home, Work) |
| `phone_area_code`      | String | Yes      | Area code                       |
| `gender`               | String | No       | Gender (MALE, FEMALE, OTHER)    |
| `birth_date`           | String | No       | Birth date (YYYY-MM-DD)         |
| `address_2`            | String | No       | Secondary address               |
| `phone_country_code`   | String | No       | Phone country code              |

#### bill\_to (Required)

| Field            | Type    | Required                 | Description         |
| ---------------- | ------- | ------------------------ | ------------------- |
| `id`             | String  | No                       | Customer identifier |
| `profile`        | String  | No                       | Customer profile    |
| All other fields | Various | Same as cardholder\_info | Same requirements   |

#### line\_items (Required)

| Field             | Type   | Required | Description               |
| ----------------- | ------ | -------- | ------------------------- |
| `id`              | String | Yes      | Item identifier           |
| `name`            | String | Yes      | Item name                 |
| `price`           | Number | Yes      | Item price                |
| `quantity`        | Number | Yes      | Item quantity             |
| `type`            | String | No       | Item type must be Generic |
| `category.id`     | String | No       | Category identifier       |
| `category.name`   | String | No       | Category name             |
| `seller_id`       | String | No       | Seller identifier         |
| `service_date`    | String | No       | Service date              |
| `discount_amount` | Number | No       | Discount applied          |

#### Device Info

<table><thead><tr><th width="222.50390625">Parameter</th><th width="108.1484375">Type</th><th width="119.70703125">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>ip_address</code></td><td>String</td><td>Yes</td><td>Customer's IP address</td></tr><tr><td><code>fingerprint_session_id</code>*</td><td>String</td><td>Yes </td><td>A unique alpha-numerical ID generated for each user session on a website.</td></tr></tbody></table>

{% hint style="info" %}
`fingerprint_session_id` is required for all KOIN requests. See [KOIN - Device Fingerprint Session ID](/api-docs/guides/koin-device-fingerprint-session-id.md) for implementation by platform (Web, Android, iOS).
{% endhint %}

#### shipping\_info (Optional)

| Field         | Type   | Required | Description                       |
| ------------- | ------ | -------- | --------------------------------- |
| `country`     | String | No       | Shipping country                  |
| `address_1`   | String | No       | Shipping address                  |
| `city`        | String | No       | Shipping city                     |
| `state`       | String | No       | Shipping state                    |
| `postal_code` | String | No       | Shipping postal code              |
| `by`          | String | No       | Shipping carrier                  |
| `date`        | String | No       | Expected delivery date            |
| `type`        | String | No       | Shipping type (STANDARD, EXPRESS) |
| `price`       | Number | No       | Shipping cost                     |

### Response Format

#### Success Response (200)

```json
{
  "status_code": 200,
  "status": "Success",
  "desc": "Payment processed successfully",
  "data": {
    "transaction_info": {
      "type": "payment_response",
      "reference_code": "1753550831362",
      "transaction_id": "0001753550831987788592",
      "request_id": "6a67ceba-9c66-4c80-b567-6f821cff007b",
      "status": "Collected",
      "response_code": "6344942",
      "created_at": "2025-07-26T17:27:17.931Z"
    },
    "order_info": {
      "amount_details": {
        "authorized_amount": 1000,
        "currency": "BRL"
      }
    },
    "risk_info": {
      "status": "Approved",
      "date": "2025-07-26T17:27:16.000Z",
      "strategies": []
    }
  }
}
```

#### Failed Payment Response (200)

```json
{
  "status": "success",
  "message": "Payment failed",
  "data": {
    "transaction_info": {
      "type": "payment_response",
      "reference_code": "1753550023570",
      "transaction_id": "0001755176590033234494",
      "request_id": "6de98d6d-1a49-438e-a648-23644c5856f1",
      "status": "Declined",
      "created_at": "2025-08-14T13:03:15.419Z"
    },
    "order_info": {
      "amount_details": {
        "authorized_amount": 10001,
        "currency": "BRL"
      }
    },
    "risk_info": {
      "status": "Approved",
      "date": "2025-08-14T13:03:14.000Z",
      "strategies": []
    },
    "error_info": {
      "reason": "InsufficientFunds",
      "message": "Transaction failed"
    }
  }
}
```

#### Error Response (400/500)

```json
{
  "status": "Fail",
  "message": "Invalid request",
  "data": {
    "code": 400,
    "description": "Invalid card data."
  }
}
```

### Response Fields

#### transaction\_info

| Field            | Type   | Description                                                      |
| ---------------- | ------ | ---------------------------------------------------------------- |
| `type`           | String | Response type (payment\_response, authorization\_response, etc.) |
| `reference_code` | String | Merchant reference code from request                             |
| `transaction_id` | String | Unique transaction identifier generated by Firstoken             |
| `request_id`     | String | Unique request identifier                                        |
| `status`         | String | Transaction status (Collected, Declined, Opened, etc.)           |
| `response_code`  | String | Internal response code                                           |
| `created_at`     | String | Transaction creation timestamp (ISO 8601)                        |

#### order\_info

| Field                              | Type   | Description          |
| ---------------------------------- | ------ | -------------------- |
| `amount_details.authorized_amount` | Number | Authorized amount    |
| `amount_details.currency`          | String | Transaction currency |

#### risk\_info

| Field        | Type   | Description                                                    |
| ------------ | ------ | -------------------------------------------------------------- |
| `status`     | String | Antifraud status: `Approved`, `Denied`                         |
| `date`       | String | Date of antifraud evaluation (ISO 8601)                        |
| `strategies` | Array  | Array of antifraud strategies applied (see Strategies section) |

#### error\_info (present when transaction fails)

| Field     | Type   | Description                                           |
| --------- | ------ | ----------------------------------------------------- |
| `reason`  | String | Failure reason (InsufficientFunds, InvalidCard, etc.) |
| `message` | String | Human-readable error message                          |

#### Antifraud Strategies

The `strategies` array contains objects with antifraud strategies that were applied to the transaction. Each strategy object contains:

| Field  | Type   | Description                                                                                       |
| ------ | ------ | ------------------------------------------------------------------------------------------------- |
| `type` | String | Strategy type (`VerificationCode` ,`DocumentScan` ,`ManualVerification` ,`CollectAuthRecovery` ") |
| `link` | String | Reference link for strategy details                                                               |

**Note**: Strategies must be configured in your KOIN account to appear in responses. If no strategies are configured, the array will be empty `[]`.

### cURL Example

```bash
curl -X POST https://api.firstoken.co/v1/payments/ \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "transaction_info": {
      "type": "payment",
      "reference_code": "ref_{{$guid}}"
    },
    "card": {
      "number": "4225289837059229",
      "expiration_date": "01/2030",
      "security_code": "123",
      "holder": "João Silva"
    },
    "order_info": {
      "amount_details": {
        "total_amount": 1000,
        "currency": "BRL",
        "items_amount": 1000
      },
      "installments": 1,
      "descriptor": "Compra Online"
    },
    "cardholder_info": {
      "first_name": "João",
      "last_name": "Silva",
      "document": {
        "type": "CPF",
        "number": "12345678901",
        "nationality": "BR"
      },
      "country": "BR",
      "address_1": "Rua das Flores, 123",
      "city": "São Paulo",
      "state": "SP",
      "postal_code": "04001-000",
      "email": "joao@example.com",
      "phone_number": "11987654321",
      "phone_type": "Mobile",
      "phone_area_code": "11"
    },
    "bill_to": {
      "id": "customer_123",
      "first_name": "João",
      "last_name": "Silva",
      "document": {
        "type": "CPF",
        "number": "12345678901",
        "nationality": "BR"
      },
      "country": "BR",
      "address_1": "Rua das Flores, 123",
      "city": "São Paulo",
      "state": "SP",
      "postal_code": "04001-000",
      "email": "joao@example.com",
      "phone_number": "11987654321",
      "phone_type": "Mobile",
      "phone_area_code": "11",
      "profile": "regular"
    },
    "line_items": [
      {
        "category": {
              "id": "1",
              "name": "Category 1"
        },
        "id": "item_001",
        "name": "Produto Teste",
        "price": 1000,
        "quantity": 1,
        "type": "Generic"
      }
    ],
    "device_info": {
      "ip_address": "192.168.1.100",
      "fingerprint_session_id": "0a76c25669713d8d6d306ba8c21259b7"
    }
  }'
```
