# 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 numerical ID generated for each user session on a website.</td></tr></tbody></table>

<p align="center"><sub>(*) The <code>fingerprint_session_id</code> is generated using a Koin script that is called from the webpage.</sub></p>

#### 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"
    }
  }'
```


---

# 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://firstoken.gitbook.io/api-docs/api-reference/payments/payments-api-koin/payments-complete-flow.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.
