> For the complete documentation index, see [llms.txt](https://developers.coincircuit.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers.coincircuit.io/changelog/readme.md).

# Changelog

New updates and improvements

Track API changes, new features, migration guides, and deprecation notices.

{% hint style="info" %}
Each release starts with the headline changes first. Expand the examples when you need implementation detail.
{% endhint %}

{% updates format="full" %}
{% update date="2026-03-01" %}

## v2.1.0 — x402 Agent Payments, Base, and Arbitrum

New endpoints now support AI agent payments with gasless stablecoin transfers. Base and Arbitrum are also now supported across payment sessions and agent payments.

### Highlights

* Added `POST /payments/agent/settle`
* Added `POST /payments/agent/verify`
* Added x402 payment session support
* Added Base and Arbitrum support

### Agent payments

#### `POST /payments/agent/settle`

Settle gasless stablecoin payments from AI agents. This endpoint accepts signed payloads from:

* `eip3009` for USDC on Base and Arbitrum
* `permit2` for USDC and USDT on Base, Arbitrum, and BSC
* `solana` for SOL, USDC, and USDT on Solana

CoinCircuit submits the transaction on-chain and covers gas.

<details>

<summary>Example request</summary>

```json
POST /api/v1/payments/agent/settle
{
  "sessionReference": "cs_ref_abc123",
  "scheme": "eip3009",
  "chain": "base",
  "asset": "USDC",
  "payload": {
    "from": "0xAgentWallet...",
    "to": "0xDepositAddress...",
    "value": "1000000",
    "validAfter": "0",
    "validBefore": "1774055094",
    "nonce": "0xrandom32bytes...",
    "signature": "0xabcd...1234"
  }
}
```

</details>

#### `POST /payments/agent/verify`

Pre-validate a signed agent payment before touching the blockchain. This runs scheme-specific checks and returns `200` for a valid payment, or `400` with per-check results.

<details>

<summary>Example request and response</summary>

```json
POST /api/v1/payments/agent/verify
{
  "scheme": "eip3009",
  "chain": "base",
  "asset": "USDC",
  "payload": { ... }
}
```

```json
{
  "valid": true,
  "checks": {
    "balance": "pass",
    "nonce": "pass",
    "authorization": "pass"
  }
}
```

</details>

#### x402 HTTP 402 payment flow

Payment sessions now work in the x402 flow.

{% stepper %}
{% step %}

### Create a payment session

Create a session with `POST /payments`.
{% endstep %}

{% step %}

### Return `402 Payment Required`

Return deposit details to the agent in the `402` response.
{% endstep %}

{% step %}

### Receive the signed payload

The agent signs the payment with `eip3009`, `permit2`, or `solana`.
{% endstep %}

{% step %}

### Settle the payment

Call `POST /payments/agent/settle` and deliver the resource.
{% endstep %}
{% endstepper %}

<details>

<summary>View end-to-end flow</summary>

```
Agent -> GET /api/premium-data
Server -> CoinCircuit: POST /payments
Server -> Agent: 402 (deposit address, amount)
Agent -> Signs payment (eip3009 / permit2 / solana)
Agent -> Server: POST /pay (signed payload)
Server -> CoinCircuit: POST /payments/agent/settle
Server -> Agent: 200 (resource delivered)
```

</details>

### Supported schemes and chains

* `eip3009` — USDC on Base and Arbitrum
* `permit2` — USDC and USDT on Base, Arbitrum, and BSC
* `solana` — SOL, USDC, and USDT on Solana

### New supported blockchains

#### Base

Base is now supported for all payment sessions. USDC on Base settles in under 2 seconds. Base is also the default chain for EIP-3009 agent payments.

#### Arbitrum

Arbitrum One is now supported for all payment sessions. It supports USDC and USDT with both EIP-3009 and Permit2.
{% endupdate %}

{% update date="2026-02-01" %}

## v2.0.0 — Payment API Transition and Payouts Unified

This release updates payment session payloads, renames webhook event types, and introduces a unified payouts API. Existing API keys keep their current behavior. New API keys use the updated format automatically.

### Highlights

* Renamed webhook event types from `session.*` to `payment.*`
* Redesigned payment session response shape
* Added inline `settlements`
* Unified payouts under `POST /payouts`
* Deprecated legacy payout endpoints

### Payment API changes

#### Webhook event types renamed

Payment session event names now use `payment.*` instead of `session.*`. The payload shape stays the same. Only the event type string changes.

{% tabs %}
{% tab title="Previous" %}

```javascript
"session.completed"
"session.expired"
"session.partial"
"session.failed"
```

{% endtab %}

{% tab title="New" %}

```javascript
"payment.completed"
"payment.expired"
"payment.partial"
"payment.underpaid"
"payment.failed"
```

{% endtab %}
{% endtabs %}

#### New API keys use the updated format automatically

Versioning is tied to your API key:

* Existing API keys keep the current response shape and event types
* New API keys use the updated response shape and webhook names
* No extra config is required

{% hint style="success" %}
No change is required to keep your current integration working. Create a new API key only when you are ready to adopt the new format.
{% endhint %}

#### Session response shape redesigned

The session response is now flatter:

* `status` is replaced by `state`
* `amount` and `currency` are now top-level strings
* `gross`, `fees`, and `net` move to `settlements`

<details>

<summary>View full session response example</summary>

```json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "reference": "cs_ref_abc123xyz789",
  "state": "closed",
  "type": "payment",
  "amount": "10000.00",
  "currency": "NGN",
  "payment": {
    "status": "completed",
    "asset": "USDT",
    "chain": "tron",
    "amount": "6.84",
    "amountReceived": "6.84",
    "address": "T...",
    "txHash": "0x..."
  },
  "settlements": {
    "currency": "NGN",
    "gross": { "amount": "10000.00", "conversionRate": "1.0" },
    "fees": {
      "processing": { "amount": "100.00", "paidBy": "merchant" },
      "gas": { "amount": "50.00", "paidBy": "merchant" }
    },
    "net": { "amount": "9850.00" }
  },
  "customer": { ... },
  "createdAt": "...",
  "expiresAt": "...",
  "completedAt": "..."
}
```

</details>

#### `state` replaces `status`

The top-level session status is now binary:

* `open` while the session is active
* `closed` once the session is finalized

The payment outcome now lives in `payment.status`.

{% tabs %}
{% tab title="Previous" %}

```javascript
{ "status": "completed" }  // "pending" | "completed" | "expired" | "failed"
```

{% endtab %}

{% tab title="New" %}

```javascript
{ "state": "closed" }      // "open" | "closed"
// payment outcome lives in payment.status
```

{% endtab %}
{% endtabs %}

#### `settlements` is now included in the payment response

Payment session responses now include settlement details inline. You no longer need a separate settlements lookup for the same breakdown.

<details>

<summary>View `settlements` example</summary>

```json
{
  "settlements": {
    "currency": "NGN",
    "gross": { "amount": "10000.00", "conversionRate": "1.0" },
    "fees": {
      "processing": { "amount": "100.00", "paidBy": "merchant" },
      "gas": { "amount": "50.00", "paidBy": "merchant" }
    },
    "net": { "amount": "9850.00" }
  }
}
```

</details>

### Payouts API changes

{% hint style="warning" %}
`/payout/fiat` and `/payout/crypto` are deprecated. They will be removed on March 30, 2026.
{% endhint %}

#### Legacy payout endpoints replaced by `/payouts`

Use the unified payouts API for both fiat and crypto payouts. Fee lookup is also now unified.

{% tabs %}
{% tab title="Previous" %}

```
POST /payout/fiat
POST /payout/crypto
GET  /payout/fiat/fee
GET  /payout/crypto/fee
```

{% endtab %}

{% tab title="New" %}

```
POST /payouts
GET  /payouts/fees
```

{% endtab %}
{% endtabs %}

#### Unified payout request body

Use `method` to choose fiat or crypto. Use `recipientId` instead of `bankAccountId` or `addressId`.

<details>

<summary>View example request</summary>

```json
{
  "method": "fiat",
  "currency": "NGN",
  "amount": "10000.00",
  "recipientId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "narration": "Payout",
  "reference": "CLIENT-REF-123"
}
```

</details>

#### Amount now means what the recipient receives

The old API treated `amount` as the total deducted from your balance. The new API treats `amount` as the amount delivered to the recipient. Fees are charged separately.

{% tabs %}
{% tab title="Previous" %}

```javascript
{ "amount": "10050.00" }
// fee: 50.00
// recipient gets: 10000.00
```

{% endtab %}

{% tab title="New" %}

```javascript
{ "amount": "10000.00" }
// fee: 50.00
// total deducted: 10050.00
```

{% endtab %}
{% endtabs %}

#### Payout response redesigned

The response now uses flat amount fields, a unified `recipient` object, and a `conversion` object when payout currency differs from the balance currency.

<details>

<summary>View full payout response example</summary>

```json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "method": "crypto",
  "type": "manual",
  "status": "success",
  "amount": "100.00",
  "fee": "1.50",
  "total": "101.50",
  "currency": "USDC",
  "conversion": {
    "from": "USDT",
    "to": "USDC",
    "rate": "0.9998",
    "convertedAmount": "100.00"
  },
  "recipient": {
    "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "type": "cryptoAddress",
    "address": "T...",
    "chain": "tron",
    "asset": "USDC"
  },
  "txHash": "0x...",
  "reference": "CLIENT-REF-123",
  "narration": "Payout",
  "createdAt": "...",
  "completedAt": "..."
}
```

</details>

### Migration guide

Follow these steps to move to the new format. You can adopt them incrementally.

{% stepper %}
{% step %}

### 1. Generate a new API key

New API keys automatically use the updated format. Keep your existing key for the current integration. Test the new key before switching production traffic.
{% endstep %}

{% step %}

### 2. Update webhook event handlers

Replace `session.*` event strings with `payment.*` equivalents in your webhook handler.

```javascript
"session.completed" -> "payment.completed"
"session.expired"   -> "payment.expired"
"session.partial"   -> "payment.partial"
"session.failed"    -> "payment.failed"
```

{% endstep %}

{% step %}

### 3. Update `payment.partial` handling

`payment.partial` is now strictly mid-flow. It only fires when the session is still open and waiting for more funds. Terminal underpayment now emits `payment.underpaid`.

```javascript
if (event === "payment.partial") {
  // data.session.state === "open"
  notifyCustomerOfPartialPayment(data.session.payment.amountReceived);
}

if (event === "payment.underpaid") {
  // data.session.state === "closed"
  initiateRefundFlow(data.session.payment.amountReceived);
}
```

{% endstep %}

{% step %}

### 4. Update session response parsing

Move parsing logic from nested `amount` fields to top-level `amount`, `currency`, and `settlements`.

```javascript
// Previous
session.status
session.amount.requested.amount
session.amount.requested.currency
session.amount.gross
session.amount.fees
session.amount.net

// New
session.state
session.amount
session.currency
session.settlements.gross
session.settlements.fees
session.settlements.net
```

{% endstep %}

{% step %}

### 5. Migrate payout endpoints

Replace legacy payout endpoints with `POST /payouts`. Add `method` to the request body. Replace `bankAccountId` or `addressId` with `recipientId`. Replace fee lookups with `GET /payouts/fees`.

```javascript
// Old
POST /payout/fiat   { balanceCurrency, amount, bankAccountId, narration }
POST /payout/crypto { balanceCurrency, amount, addressId }

// New
POST /payouts {
  method: "fiat" | "crypto",
  currency: "NGN",
  amount: "10000.00",
  recipientId: "...",
  narration: "...",
  reference: "..."
}
```

{% endstep %}

{% step %}

### 6. Update payout amount handling

Remove any logic that adds fees into the request amount. In the new API, `amount` is the amount the recipient receives.

```javascript
// Old
const amount = recipientAmount + fee;
POST /payout/fiat { amount: "10050.00" }

// New
POST /payouts { amount: "10000.00" }
```

{% endstep %}

{% step %}

### 7. Update payout response parsing

Move response parsing from nested amount and endpoint-specific recipient objects to flat fields and the unified `recipient` object.

```javascript
// Old response fields
payout.amount.gross
payout.amount.fee
payout.amount.net
payout.amount.currency
payout.bankAccount
payout.crypto.amount
payout.crypto.chain
payout.crypto.address

// New response fields
payout.amount
payout.fee
payout.total
payout.currency
payout.recipient.type
payout.recipient.address
payout.recipient.chain
payout.recipient.bankName
payout.conversion
```

{% endstep %}
{% endstepper %}
{% endupdate %}
{% endupdates %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://developers.coincircuit.io/changelog/readme.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
