# Add a counterparty

`POST /api/v1/counterparties`

Adds a vendor, contractor or client, checked by the rules of the console's form and screened as one added there: the answer's `riskLevel` is the screening's verdict, or `unscreened` when screening could not finish. It is recorded in the ledger as `create_counterparty` with `via: "api"` and the key's id.

An address added through the API waits for a person. The agent pays nothing to it until an owner, admin or approver confirms it on Counterparties, so a key can add records but cannot point the agent's payments at a new address.

Send a [workspace API key](https://www.vestiarion.xyz/docs/get-started/authentication) with read and write access as `Authorization: Bearer <key>`. A read-only key gets `403`.

## Parameters

| Name | In | Type | Required | Default | Allowed values | Description |
| --- | --- | --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | string | Optional | — | — | Makes a retry safe: up to 255 printable ASCII characters, unique to the record being added, such as its id in your own system. A repeat with the same key and the same body within 24 hours gets the first answer back, with `Idempotent-Replayed: true`, and adds nothing. The same key with a different body answers `409`. |

## Request body

Example, `application/json`:

```json
{
  "name": "API Test Vendor",
  "role": "vendor",
  "address": "0x6b3A4C65f362b818bb7FD6f999477A03CE07e51a",
  "paymentLimit": "1"
}
```

**Fields**

- `name` (string, required): 2 to 160 characters.
- `role` (string, required): `vendor` or `contractor`, whom the business pays, or `client`, who pays the business. One of `vendor`, `client`, `contractor`.
- `address` (string, optional): Where the agent pays it. An address added through the API waits for a person in the workspace to confirm it on Counterparties; until then the agent pays nothing to it.
- `chain` (string, optional): The chain the address receives on. Defaults to `ARC-TESTNET`; only a vendor can be paid on another chain. One of `ARC-TESTNET`, `BASE-SEPOLIA`, `ARB-SEPOLIA`, `ETH-SEPOLIA`.
- `jurisdiction` (string, optional): Where it is based, up to 80 characters; screening uses it.
- `paymentLimit` (string | number, optional): The most the agent pays it in one payment, in USDC, with up to 6 decimal places. Required for a vendor or a contractor.
- `noticeEmail` (string, optional): Where it is emailed once a payment to it is confirmed.

## Code samples

```bash
curl "https://www.vestiarion.xyz/api/v1/counterparties" \
  -X POST \
  -H "Authorization: Bearer $VESTIARION_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: crm-vendor-1042" \
  -d '{"name":"API Test Vendor","role":"vendor","address":"0x6b3A4C65f362b818bb7FD6f999477A03CE07e51a","paymentLimit":"1"}'
```

## Response

Example, `201` `application/json`:

```json
{
  "data": {
    "id": "6b361405-cfda-4400-a286-364b561911ce",
    "name": "API Test Vendor",
    "role": "vendor",
    "address": "0x6b3A4C65f362b818bb7FD6f999477A03CE07e51a",
    "chain": "ARC-TESTNET",
    "jurisdiction": null,
    "riskLevel": "clear",
    "riskNotes": "OpenSanctions returned no matching entity",
    "baselinePaymentLimit": 1,
    "paymentLimit": 1,
    "lastScreenedAt": "2026-10-03T10:15:29.759+00:00",
    "performanceScore": null,
    "performanceInputs": null,
    "createdAt": "2026-10-03T10:15:26.865688+00:00"
  }
}
```

**Fields**

- `data` (object, required): A vendor, client or contractor, with its risk tier and payment limits.
  - `id` (string, required)
  - `name` (string, required)
  - `role` (string, required) One of `vendor`, `client`, `contractor`.
  - `address` (string, nullable, required)
  - `chain` (string, nullable, required)
  - `jurisdiction` (string, nullable, required)
  - `riskLevel` (string, required) One of `unscreened`, `clear`, `medium`, `high`.
  - `riskNotes` (string, nullable, required)
  - `baselinePaymentLimit` (number, nullable, required): The business's baseline payment limit for this counterparty.
  - `paymentLimit` (number, nullable, required): The current payment limit, derived from the risk tier.
  - `lastScreenedAt` (string, nullable, required)
  - `performanceScore` (number, nullable, required): No history is different from a zero score and remains null.
  - `performanceInputs` (object, nullable, required)
  - `createdAt` (string, required)

## Errors

| Status | Code | When |
| --- | --- | --- |
| 400 | `invalid_request` | An invalid `limit` or `cursor`, a filter value outside its allowed values, or a request body that does not validate. The message names the parameter or the field, and lists the accepted values. |
| 401 | `unauthorized` | No key, or a malformed, unknown or revoked one: "A valid API key is required." |
| 403 | `forbidden` | The key's scopes do not cover this route: "This key cannot do that." Or, on a write, the person who created the key can no longer add records: "This key's issuer can no longer add records in this workspace." |
| 409 | `conflict` | The `Idempotency-Key` was already used for a different request, or the first request with it is still being handled. |
| 429 | `rate_limited` | Too many requests; wait as long as `Retry-After` says before trying again. |
| 500 | `internal` | An unexpected server error. Implementation details are not exposed. |
