# Ingest transactions

Push bank transactions from an integration.

Synchronously inserts up to 1000 transactions. The tenant is taken from the API key. Duplicate sourceType+sourceId rows are skipped. Matching jobs are published for non-ignored inserts. This call does not create an import job; List ingest jobs is for file imports. Requires a tenant API key with `ingest:write` (Firebase tokens are rejected).


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



## Body parameters

| Name | Type | Required | Description | Allowed values | Example |
| --- | --- | --- | --- | --- | --- |
| `transactions` | array | required | Rows to ingest. Minimum 1, maximum 1000. Extra top-level fields are rejected. |  |  |
| `transactions.sourceId` | string, max 255 | required | Your unique id for this movement. Together with sourceType this is the idempotency key. |  | `bank:2026-09-12:TX-8891` |
| `transactions.amount` | number | required | Positive amount in major currency units, unless the tenant stores minor units. |  | `1000` |
| `transactions.direction` | string, no maximum | required | Payment direction. debit/credit and inbound/outbound are accepted aliases of in/out. | `in`, `out`, `debit`, `credit`, `inbound`, `outbound` |  |
| `transactions.transactionDate` | string, no maximum | required | Transaction date (YYYY-MM-DD or ISO timestamp). |  | `2026-09-12` |
| `transactions.sourceType` | string, no maximum | optional | Origin of the record. Default api. | `api`, `csv`, `enable_banking`, `camt_052`, `camt_053`, `camt_054`, `mt940` |  |
| `transactions.currency` | string, max 3 | recommended | ISO 4217 currency. Default EUR. |  | `EUR` |
| `transactions.bookingDate` | string, no maximum | optional | Booking date. |  | `2026-09-12` |
| `transactions.valueDate` | string, no maximum | optional | Value date. |  | `2026-09-12` |
| `transactions.descriptionOriginal` | string, max 1000 | optional | Bank wording. |  | `VIREMENT LEONES CARS` |
| `transactions.descriptionDisplay` | string, max 1000 | optional | Display wording. |  | `Leones Cars — wire payment` |
| `transactions.externalReference` | string, max 255 | optional | End-to-end or invoice reference. |  | `INV-2026-0042` |
| `transactions.remittanceInfo` | string, max 500 | optional | Unstructured remittance information. |  | `INV-2026-0042 Leones Cars` |
| `transactions.structuredReference` | string, max 255 | optional | Structured creditor reference. |  | `RF18539007547034` |
| `transactions.counterpartyName` | string, max 255 | optional | Name as received from the bank. |  | `Leones Cars` |
| `transactions.counterpartyIban` | string, max 50 | optional | Counterparty IBAN. |  | `FR7630006000011234567890189` |
| `transactions.counterpartyBic` | string, max 11 | optional | Counterparty BIC. |  | `BNPAFRPP` |
| `transactions.counterpartyIdentifier` | string, max 255 | optional | Non-IBAN counterparty instrument key. |  | `carl@leonescars.fr` |
| `transactions.flowType` | string, no maximum | optional | Economic flow type (payment, refund, fee, and similar). |  | `payment` |
| `transactions.analytic1` | string, max 100 | optional | Analytic axis 1. |  | `SALES-EU` |
| `transactions.analytic2` | string, max 100 | optional | Analytic axis 2. |  | `CHANNEL-DIRECT` |
| `transactions.sourceRaw` | object | optional | Original bank payload as JSON. At most 32 keys, nested depth 3, 8 KB serialized, and 64-character key names. Keys __proto__, constructor, and prototype are rejected. |  | `{"bookingDate":"2026-09-12"}` |
| `transactions.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. |  | `{"bank_tx_id":"EB-991"}` |

## 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 ingest:write` | `403` | The key does not include ingest: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. |
| `Too many ingest requests, please try again later` | `429` | POST /ingest/transactions is limited to 10 requests per minute per API key, on top of the general limit. Retry-After is in seconds. |
| `Invalid API key` | `401` | The Bearer token is not a tenant API key. This operation is API-key-only. |
| `API key is not bound to a tenant` | `400` | The key exists but has no tenant. |
| `Validation failed` | `400` | The body failed schema validation. details lists field and message. |
| `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/ingest/transactions \
  --header 'accept: application/json' \
  --header 'authorization: Bearer uk_live_YOUR_API_KEY' \
  --header 'content-type: application/json' \
  --data '{
  "transactions": [
    {
      "sourceType": "api",
      "sourceId": "bank:2026-09-12:TX-8891",
      "amount": 1000,
      "direction": "in",
      "currency": "EUR",
      "transactionDate": "2026-09-12",
      "descriptionOriginal": "VIREMENT LEONES CARS",
      "counterpartyName": "Leones Cars",
      "counterpartyIban": "FR7630006000011234567890189",
      "externalReference": "INV-2026-0042"
    }
  ]
}'
```

## Request (Python)

```python
import requests

url = "https://api.invunion.com/api/v1/ingest/transactions"
headers = {
    "Accept": "application/json",
    "Authorization": "Bearer uk_live_YOUR_API_KEY",
    "Content-Type": "application/json",
}
payload = {
    "transactions": [
        {
            "sourceType": "api",
            "sourceId": "bank:2026-09-12:TX-8891",
            "amount": 1000,
            "direction": "in",
            "currency": "EUR",
            "transactionDate": "2026-09-12",
            "descriptionOriginal": "VIREMENT LEONES CARS",
            "counterpartyName": "Leones Cars",
            "counterpartyIban": "FR7630006000011234567890189",
            "externalReference": "INV-2026-0042"
        }
    ]
}
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/ingest/transactions")
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  \"transactions\": [\n    {\n      \"sourceType\": \"api\",\n      \"sourceId\": \"bank:2026-09-12:TX-8891\",\n      \"amount\": 1000,\n      \"direction\": \"in\",\n      \"currency\": \"EUR\",\n      \"transactionDate\": \"2026-09-12\",\n      \"descriptionOriginal\": \"VIREMENT LEONES CARS\",\n      \"counterpartyName\": \"Leones Cars\",\n      \"counterpartyIban\": \"FR7630006000011234567890189\",\n      \"externalReference\": \"INV-2026-0042\"\n    }\n  ]\n}"
response = http.request(request)
puts response.body
```

## Request (JavaScript)

```javascript
const response = await fetch("https://api.invunion.com/api/v1/ingest/transactions", {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "Authorization": "Bearer uk_live_YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
  "transactions": [
    {
      "sourceType": "api",
      "sourceId": "bank:2026-09-12:TX-8891",
      "amount": 1000,
      "direction": "in",
      "currency": "EUR",
      "transactionDate": "2026-09-12",
      "descriptionOriginal": "VIREMENT LEONES CARS",
      "counterpartyName": "Leones Cars",
      "counterpartyIban": "FR7630006000011234567890189",
      "externalReference": "INV-2026-0042"
    }
  ]
}),
});
const data = await response.json();
```

## Request (Go)

```go
package main

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

func main() {
	payload := []byte(`{
  "transactions": [
    {
      "sourceType": "api",
      "sourceId": "bank:2026-09-12:TX-8891",
      "amount": 1000,
      "direction": "in",
      "currency": "EUR",
      "transactionDate": "2026-09-12",
      "descriptionOriginal": "VIREMENT LEONES CARS",
      "counterpartyName": "Leones Cars",
      "counterpartyIban": "FR7630006000011234567890189",
      "externalReference": "INV-2026-0042"
    }
  ]
}`)
	req, err := http.NewRequest("POST", "https://api.invunion.com/api/v1/ingest/transactions", 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/ingest/transactions", {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "Authorization": "Bearer uk_live_YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
  "transactions": [
    {
      "sourceType": "api",
      "sourceId": "bank:2026-09-12:TX-8891",
      "amount": 1000,
      "direction": "in",
      "currency": "EUR",
      "transactionDate": "2026-09-12",
      "descriptionOriginal": "VIREMENT LEONES CARS",
      "counterpartyName": "Leones Cars",
      "counterpartyIban": "FR7630006000011234567890189",
      "externalReference": "INV-2026-0042"
    }
  ]
}),
});
console.log(await response.json());
```

## Success (200)

```json
{
  "success": true,
  "data": {
    "inserted": 1,
    "skipped": 0,
    "errors": 0,
    "duplicates": [],
    "errorDetails": [],
    "createdIds": [
      "2d0e6679-7425-40de-944b-e07fc1f90ae7"
    ]
  }
}
```
