# Bulk import counterparties

Import counterparties in bulk.

Creates up to 500 counterparties in one request. Each row needs name_original (or name). If identity lookup finds an existing counterparty, the row is skipped: no update, no extra payment method. Nested payment_method with iban or identifier creates a catalog instrument on a new counterparty. Invalid association_mode skips the catalog instrument and keeps the tiers. Invalid country on a row is stored as empty rather than failing the batch.


- HTTP method: `POST`
- Path: `/api/v1/counterparties/bulk`
- URL: `https://api.invunion.com/api/v1/counterparties/bulk`
- Required scope: `counterparties:write`
- HTML docs: https://www.invunion.com/knowledge-base/api/bulk-import-counterparties/
- Markdown docs: https://www.invunion.com/knowledge-base/api/bulk-import-counterparties.md



## Body parameters

| Name | Type | Required | Description | Allowed values | Example |
| --- | --- | --- | --- | --- | --- |
| `counterparties` | array | required | Rows to import. Maximum 500. Each object accepts the same identity fields as create, plus optional nested payment_method. |  |  |
| `counterparties.name_original` | string, max 255 | required | Required on each row. name is accepted as an alias. |  | `Leones Cars` |
| `counterparties.name_display` | string, max 255 | optional | Display name shown in the product. Defaults to empty when omitted. |  | `Leones Cars` |
| `counterparties.account_code` | string, max 50 | recommended | Your account code. Unique per tenant. If omitted, Invunion assigns CPT-NNN. |  | `CPT-042` |
| `counterparties.category` | string, max 50 | recommended | Legal form of the counterparty. Default professional. | `individual`, `professional`, `governmental` |  |
| `counterparties.payment_terms_days` | integer | optional | Payment terms in days, 0 to 365. If omitted, tenant default applies. |  | `30` |
| `counterparties.is_supplier` | boolean | optional | Supplier role. Default false. | `true`, `false` |  |
| `counterparties.is_client` | boolean | optional | Client role. Default true on create. | `true`, `false` |  |
| `counterparties.is_partner` | boolean | optional | Partner role. Default false. | `true`, `false` |  |
| `counterparties.is_payer` | boolean | optional | Payer role. Default false. | `true`, `false` |  |
| `counterparties.is_internal` | boolean | optional | Internal entity. Default false. | `true`, `false` |  |
| `counterparties.is_employee` | boolean | optional | Employee. Default false. | `true`, `false` |  |
| `counterparties.external_reference` | string, max 255 | optional | External reference. Your ERP or billing customer id. Used for identity lookup. |  | `ERP-1842` |
| `counterparties.vat_number` | string, max 50 | optional | VAT number. Used for identity lookup on import. |  | `FR12345678901` |
| `counterparties.registration_number` | string, max 100 | optional | National ID (SIREN, company number, and similar). |  | `123456789` |
| `counterparties.electronic_address` | string, max 255 | optional | E-invoicing address (Peppol and similar). |  | `0208:123456789` |
| `counterparties.address` | string, no maximum | optional | Street address. |  | `12 Grove Street` |
| `counterparties.city` | string, max 255 | optional | City. |  | `Lyon` |
| `counterparties.postal_code` | string, max 20 | optional | Postal code. |  | `69001` |
| `counterparties.country` | string, no maximum | optional | Country name or ISO 3166-1 alpha-2 code. Stored as alpha-2. Invalid values return 400 on create. |  | `FR` |
| `counterparties.email` | string, no maximum | optional | Contact email. |  | `carl@leonescars.fr` |
| `counterparties.phone` | string, max 50 | optional | Phone number. |  | `+33472000000` |
| `counterparties.analytic_1` | string, max 100 | optional | Analytic axis 1. |  | `SALES-EU` |
| `counterparties.analytic_2` | string, max 100 | optional | Analytic axis 2. |  | `CHANNEL-DIRECT` |
| `counterparties.metadata` | object | optional | JSON object. At most 32 keys, nested depth 3, 8 KB serialized, and 64-character key names. Keys __proto__, constructor, and prototype are rejected. |  | `{"erp_id":"C-1842"}` |
| `counterparties.payment_method` | object | recommended | Optional catalog instrument on this new counterparty. Same fields as POST /payment-methods except counterparty_id (implied). Requires iban or identifier. Aggregator IBANs and exclusive instruments owned elsewhere are skipped; the counterparty is still created. |  |  |
| `counterparties.payment_method.name` | string, max 255 | optional | Instrument display name. Defaults to name_original. |  | `Leones Cars EUR` |
| `counterparties.payment_method.iban` | string, max 50 | recommended | IBAN. Required unless identifier is set. Unique per tenant catalog. BIC alone is not enough. |  | `FR7630006000011234567890189` |
| `counterparties.payment_method.identifier` | string, max 120 | optional | Non-IBAN instrument key (PayPal email, wallet id, terminal number). Required unless iban is set. Unique per tenant catalog. |  | `carl@leonescars.fr` |
| `counterparties.payment_method.code` | string, max 50 | recommended | Your payment-method code. Unique per tenant. If omitted, Invunion assigns PM-NNN. |  | `PM-001` |
| `counterparties.payment_method.type` | string, no maximum | recommended | Instrument type. Default bank_account. | `bank_account`, `credit_card`, `paypal`, `wero`, `twint`, `crypto_wallet`, `other` |  |
| `counterparties.payment_method.bic` | string, max 11 | optional | BIC. Bank name and country are filled from the BIC directory when omitted. |  | `BNPAFRPP` |
| `counterparties.payment_method.currency` | string, max 3 | optional | ISO 4217 currency code. Default EUR. |  | `EUR` |
| `counterparties.payment_method.association_mode` | string, no maximum | recommended | exclusive (one owner) or shared (several counterparties). Default exclusive. Applies only when creating a new catalog instrument; an existing shared IBAN stays shared. | `exclusive`, `shared` |  |
| `counterparties.payment_method.account_type` | string, no maximum | optional | Optional account type label. |  | `checking` |
| `counterparties.payment_method.bank_name` | string, no maximum | optional | Bank name. Filled from BIC when omitted. |  | `BNP Paribas` |
| `counterparties.payment_method.bank_country` | string, no maximum | optional | ISO 3166-1 alpha-2 of the bank, not the counterparty country. |  | `FR` |
| `counterparties.payment_method.status` | string, no maximum | optional | Instrument status. Default active. | `active`, `inactive`, `error` |  |
| `counterparties.payment_method.metadata` | object | optional | JSON object. At most 32 keys, nested depth 3, 8 KB serialized, and 64-character key names. Keys __proto__, constructor, and prototype are rejected. |  | `{"erp_pm":"BANK-042"}` |

## Errors

| Error | HTTP code | Description |
| --- | --- | --- |
| `Missing Bearer token` | `401` | The Authorization header is missing or is not a Bearer token. |
| `Invalid or revoked API key` | `401` | The API key is unknown, malformed, expired, or has been revoked. |
| `API key is missing scope counterparties:write` | `403` | The key does not include counterparties:write. A write scope does not imply the matching read scope. |
| `Too many requests, please try again later` | `429` | Wait and retry. The Retry-After header is the number of seconds to wait. |
| `Tenant ID required` | `400` | The authenticated credential is not bound to a tenant. |
| `counterparties must be a non-empty array` | `400` | The body is missing counterparties, or the array is empty. |
| `Maximum 500 counterparties per bulk import` | `400` | The array contains more than 500 rows. |
| `Internal server error` | `500` | Unexpected server error. The JSON body includes correlationId. Retry with backoff. |

## Request (curl)

```bash
curl --request POST \
  --url https://api.invunion.com/api/v1/counterparties/bulk \
  --header 'accept: application/json' \
  --header 'authorization: Bearer uk_live_YOUR_API_KEY' \
  --header 'content-type: application/json' \
  --data '{
  "counterparties": [
    {
      "name_original": "Leones Cars",
      "name_display": "Leones Cars",
      "category": "professional",
      "payment_terms_days": 30,
      "is_client": true,
      "is_payer": true,
      "external_reference": "ERP-1842",
      "vat_number": "FR12345678901",
      "country": "FR",
      "city": "Lyon",
      "email": "carl@leonescars.fr",
      "payment_method": {
        "name": "Leones Cars EUR",
        "iban": "FR7630006000011234567890189",
        "bic": "BNPAFRPP",
        "type": "bank_account",
        "association_mode": "exclusive"
      }
    },
    {
      "name_original": "Grove Street Garage",
      "country": "US",
      "is_supplier": true,
      "payment_method": {
        "name": "Grove Street Garage PayPal",
        "identifier": "accounts@grovestreet.example",
        "type": "paypal",
        "association_mode": "exclusive"
      }
    }
  ]
}'
```

## Request (Python)

```python
import requests

url = "https://api.invunion.com/api/v1/counterparties/bulk"
headers = {
    "Accept": "application/json",
    "Authorization": "Bearer uk_live_YOUR_API_KEY",
    "Content-Type": "application/json",
}
payload = {
    "counterparties": [
        {
            "name_original": "Leones Cars",
            "name_display": "Leones Cars",
            "category": "professional",
            "payment_terms_days": 30,
            "is_client": True,
            "is_payer": True,
            "external_reference": "ERP-1842",
            "vat_number": "FR12345678901",
            "country": "FR",
            "city": "Lyon",
            "email": "carl@leonescars.fr",
            "payment_method": {
                "name": "Leones Cars EUR",
                "iban": "FR7630006000011234567890189",
                "bic": "BNPAFRPP",
                "type": "bank_account",
                "association_mode": "exclusive"
            }
        },
        {
            "name_original": "Grove Street Garage",
            "country": "US",
            "is_supplier": True,
            "payment_method": {
                "name": "Grove Street Garage PayPal",
                "identifier": "accounts@grovestreet.example",
                "type": "paypal",
                "association_mode": "exclusive"
            }
        }
    ]
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```

## Request (Ruby)

```ruby
require 'net/http'
require 'json'
require 'uri'

uri = URI("https://api.invunion.com/api/v1/counterparties/bulk")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['Accept'] = 'application/json'
request['Authorization'] = 'Bearer uk_live_YOUR_API_KEY'
request['Content-Type'] = 'application/json'
request.body = "{\n  \"counterparties\": [\n    {\n      \"name_original\": \"Leones Cars\",\n      \"name_display\": \"Leones Cars\",\n      \"category\": \"professional\",\n      \"payment_terms_days\": 30,\n      \"is_client\": true,\n      \"is_payer\": true,\n      \"external_reference\": \"ERP-1842\",\n      \"vat_number\": \"FR12345678901\",\n      \"country\": \"FR\",\n      \"city\": \"Lyon\",\n      \"email\": \"carl@leonescars.fr\",\n      \"payment_method\": {\n        \"name\": \"Leones Cars EUR\",\n        \"iban\": \"FR7630006000011234567890189\",\n        \"bic\": \"BNPAFRPP\",\n        \"type\": \"bank_account\",\n        \"association_mode\": \"exclusive\"\n      }\n    },\n    {\n      \"name_original\": \"Grove Street Garage\",\n      \"country\": \"US\",\n      \"is_supplier\": true,\n      \"payment_method\": {\n        \"name\": \"Grove Street Garage PayPal\",\n        \"identifier\": \"accounts@grovestreet.example\",\n        \"type\": \"paypal\",\n        \"association_mode\": \"exclusive\"\n      }\n    }\n  ]\n}"
response = http.request(request)
puts response.body
```

## Request (JavaScript)

```javascript
const response = await fetch("https://api.invunion.com/api/v1/counterparties/bulk", {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "Authorization": "Bearer uk_live_YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
  "counterparties": [
    {
      "name_original": "Leones Cars",
      "name_display": "Leones Cars",
      "category": "professional",
      "payment_terms_days": 30,
      "is_client": true,
      "is_payer": true,
      "external_reference": "ERP-1842",
      "vat_number": "FR12345678901",
      "country": "FR",
      "city": "Lyon",
      "email": "carl@leonescars.fr",
      "payment_method": {
        "name": "Leones Cars EUR",
        "iban": "FR7630006000011234567890189",
        "bic": "BNPAFRPP",
        "type": "bank_account",
        "association_mode": "exclusive"
      }
    },
    {
      "name_original": "Grove Street Garage",
      "country": "US",
      "is_supplier": true,
      "payment_method": {
        "name": "Grove Street Garage PayPal",
        "identifier": "accounts@grovestreet.example",
        "type": "paypal",
        "association_mode": "exclusive"
      }
    }
  ]
}),
});
const data = await response.json();
```

## Request (Go)

```go
package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
)

func main() {
	payload := []byte(`{
  "counterparties": [
    {
      "name_original": "Leones Cars",
      "name_display": "Leones Cars",
      "category": "professional",
      "payment_terms_days": 30,
      "is_client": true,
      "is_payer": true,
      "external_reference": "ERP-1842",
      "vat_number": "FR12345678901",
      "country": "FR",
      "city": "Lyon",
      "email": "carl@leonescars.fr",
      "payment_method": {
        "name": "Leones Cars EUR",
        "iban": "FR7630006000011234567890189",
        "bic": "BNPAFRPP",
        "type": "bank_account",
        "association_mode": "exclusive"
      }
    },
    {
      "name_original": "Grove Street Garage",
      "country": "US",
      "is_supplier": true,
      "payment_method": {
        "name": "Grove Street Garage PayPal",
        "identifier": "accounts@grovestreet.example",
        "type": "paypal",
        "association_mode": "exclusive"
      }
    }
  ]
}`)
	req, err := http.NewRequest("POST", "https://api.invunion.com/api/v1/counterparties/bulk", bytes.NewBuffer(payload))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Authorization", "Bearer uk_live_YOUR_API_KEY")
	req.Header.Set("Content-Type", "application/json")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	body, _ := io.ReadAll(resp.Body)
	fmt.Println(string(body))
}
```

## Request (Node)

```javascript
const response = await fetch("https://api.invunion.com/api/v1/counterparties/bulk", {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "Authorization": "Bearer uk_live_YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
  "counterparties": [
    {
      "name_original": "Leones Cars",
      "name_display": "Leones Cars",
      "category": "professional",
      "payment_terms_days": 30,
      "is_client": true,
      "is_payer": true,
      "external_reference": "ERP-1842",
      "vat_number": "FR12345678901",
      "country": "FR",
      "city": "Lyon",
      "email": "carl@leonescars.fr",
      "payment_method": {
        "name": "Leones Cars EUR",
        "iban": "FR7630006000011234567890189",
        "bic": "BNPAFRPP",
        "type": "bank_account",
        "association_mode": "exclusive"
      }
    },
    {
      "name_original": "Grove Street Garage",
      "country": "US",
      "is_supplier": true,
      "payment_method": {
        "name": "Grove Street Garage PayPal",
        "identifier": "accounts@grovestreet.example",
        "type": "paypal",
        "association_mode": "exclusive"
      }
    }
  ]
}),
});
console.log(await response.json());
```

## Success (201)

```json
{
  "success": true,
  "data": {
    "inserted": 2,
    "skipped": 0,
    "payment_methods_attached": 2,
    "payment_methods_created": 2,
    "payment_methods_skipped": 0,
    "payment_method_conflicts": [],
    "total": 2,
    "errors": []
  },
  "message": "2 counterparties imported, 0 skipped"
}
```
