# Create import job

Import up to 10,000 transactions, invoices, counterparties, or payment methods in the background.

Stages the items and answers 202 with a job id right away. Rows are processed in the background; follow them with Get import job. This is the recommended way to push data in volume, and it replaces Ingest transactions.

`items` takes the same fields as the single-record call for that entity: an Ingest transactions row for `transaction`, the Create invoice body for `invoice` (issued invoices by default), a Bulk import counterparties row for `counterparty`, and a Bulk import payment methods row for `payment_method`. Transaction rows are validated before the job is created: if any row is invalid, nothing is staged and the call returns 400 with up to 20 row errors.

The key needs `ingest:write` and the write scope of the entity. Send an `Idempotency-Key` header so a retried request does not create a second job. Limited to 20 requests per minute per key.

## See also

- [Get import job](https://www.invunion.com/knowledge-base/api/get-import-job/) (`GET /api/v1/import-jobs/:id`). Follow the job and read per-row errors.
- [Ingest transactions (deprecated)](https://www.invunion.com/knowledge-base/api/ingest-transactions/) (`POST /api/v1/ingest/transactions`). Older synchronous call for small transaction batches.
- [Retries and rate limits](https://www.invunion.com/knowledge-base/api/idempotency/). Retry safely with Idempotency-Key.

- HTTP method: `POST`
- Path: `/api/v1/import-jobs`
- URL: `https://api.invunion.com/api/v1/import-jobs`
- Required scope: `ingest:write`
- Idempotency-Key header: accepted. See https://www.invunion.com/knowledge-base/api/idempotency/
- HTML docs: https://www.invunion.com/knowledge-base/api/create-import-job/
- Markdown docs: https://www.invunion.com/knowledge-base/api/create-import-job.md



## Body parameters

| Name | Type | Required | Description | Allowed values | Example |
| --- | --- | --- | --- | --- | --- |
| `entity` | string, no maximum | required | What the items are. | `transaction`, `invoice`, `counterparty`, `payment_method` |  |
| `items` | array | required | Records to import, 1 to 10,000. Fields depend on entity (see above). |  | `[{"sourceId":"bank:2026-09-12:TX-8891","amount":1000,"direction":"in","transactionDate":"2026-09-12"}]` |
| `fileName` | string, max 255 | optional | Label shown on the job. Default `<entity>-api-import.json`. |  | `september-bank-lines.json` |

## 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` | More than 100 requests in one minute from this API key or IP address. Wait for the Retry-After header (seconds) and retry. |
| `Too many import requests, please try again later` | `429` | POST /import-jobs is limited to 20 requests per minute per API key, on top of the general limit. Retry-After is in seconds. |
| `API key is missing scope …` | `403` | Besides ingest:write, the key needs the write scope of the entity: ingest:write for transactions, invoices:write, counterparties:write, or payment_methods:write. code is missing_scope. |
| `Invalid import request` | `400` | entity is unknown, items is empty or has more than 10,000 entries, or the body has extra fields. details lists field and message. |
| `Some transactions are invalid` | `400` | At least one transaction row failed validation. details lists up to 20 rows with their messages. Nothing was staged. |
| `Tenant context required` | `400` | The authenticated credential is not bound to a tenant. |
| `Internal server error` | `500` | Unexpected server error. The JSON body includes correlationId. Retry with backoff. |
| `Idempotency-Key must be 8-255 characters: letters, digits, ".", "_", ":" or "-".` | `400` | The Idempotency-Key header is present but malformed. |
| `A request with this Idempotency-Key is still being processed.` | `409` | The first request with this key has not finished. Retry after it completes. code is idempotency_in_progress. |
| `This Idempotency-Key was already used with a different request body.` | `422` | Send a new key for a different request. code is idempotency_key_reuse. |

## Request (curl)

```bash
curl --request POST \
  --url https://api.invunion.com/api/v1/import-jobs \
  --header 'accept: application/json' \
  --header 'authorization: Bearer uk_live_YOUR_API_KEY' \
  --header 'content-type: application/json' \
  --data '{
  "entity": "transaction",
  "fileName": "september-bank-lines.json",
  "items": [
    {
      "sourceType": "api",
      "sourceId": "bank:2026-09-12:TX-8891",
      "amount": 1000,
      "direction": "in",
      "currency": "EUR",
      "transactionDate": "2026-09-12",
      "counterpartyName": "Leones Cars",
      "counterpartyIban": "FR7630006000011234567890189",
      "externalReference": "INV-2026-0042"
    }
  ]
}'
```

## Request (Python)

```python
import requests

url = "https://api.invunion.com/api/v1/import-jobs"
headers = {
    "Accept": "application/json",
    "Authorization": "Bearer uk_live_YOUR_API_KEY",
    "Content-Type": "application/json",
}
payload = {
    "entity": "transaction",
    "fileName": "september-bank-lines.json",
    "items": [
        {
            "sourceType": "api",
            "sourceId": "bank:2026-09-12:TX-8891",
            "amount": 1000,
            "direction": "in",
            "currency": "EUR",
            "transactionDate": "2026-09-12",
            "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/import-jobs")
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  \"entity\": \"transaction\",\n  \"fileName\": \"september-bank-lines.json\",\n  \"items\": [\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      \"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/import-jobs", {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "Authorization": "Bearer uk_live_YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
  "entity": "transaction",
  "fileName": "september-bank-lines.json",
  "items": [
    {
      "sourceType": "api",
      "sourceId": "bank:2026-09-12:TX-8891",
      "amount": 1000,
      "direction": "in",
      "currency": "EUR",
      "transactionDate": "2026-09-12",
      "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(`{
  "entity": "transaction",
  "fileName": "september-bank-lines.json",
  "items": [
    {
      "sourceType": "api",
      "sourceId": "bank:2026-09-12:TX-8891",
      "amount": 1000,
      "direction": "in",
      "currency": "EUR",
      "transactionDate": "2026-09-12",
      "counterpartyName": "Leones Cars",
      "counterpartyIban": "FR7630006000011234567890189",
      "externalReference": "INV-2026-0042"
    }
  ]
}`)
	req, err := http.NewRequest("POST", "https://api.invunion.com/api/v1/import-jobs", 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/import-jobs", {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "Authorization": "Bearer uk_live_YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
  "entity": "transaction",
  "fileName": "september-bank-lines.json",
  "items": [
    {
      "sourceType": "api",
      "sourceId": "bank:2026-09-12:TX-8891",
      "amount": 1000,
      "direction": "in",
      "currency": "EUR",
      "transactionDate": "2026-09-12",
      "counterpartyName": "Leones Cars",
      "counterpartyIban": "FR7630006000011234567890189",
      "externalReference": "INV-2026-0042"
    }
  ]
}),
});
console.log(await response.json());
```

## Success (202)

```json
{
  "success": true,
  "data": {
    "jobId": "6a4deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
    "entity": "transaction",
    "totalRows": 1,
    "status": "pending"
  }
}
```
