A Job is the asynchronous unit of work behind every bulk write in this API. When you POST /articles, POST /customers, or POST /suppliers, Mercura validates the payload, persists an ImportRun row, enqueues a worker task, and returns a JobAck immediately. The actual ingestion (validation per row, upsert into the catalogue, error aggregation) happens out-of-band.
GET /jobs/{job_id} is how you learn what happened. Subscribe to the job.finished webhook (see Webhooks) to be told the moment a job ends instead of polling for it.
POST /articles
Authorization: Bearer mrc_live_...
Idempotency-Key: nightly-sync-2026-05-19
Content-Type: application/json
{ "articles": [ ... up to 100,000 rows ... ] }
→ 202 Accepted
{ "job_id": "4242", "status_url": "/api/public/v1/jobs/4242" }Then poll:
GET /api/public/v1/jobs/4242
→ 200 OK
{
"job_id": "4242",
"entity": "ARTICLES",
"status": "RUNNING",
"created_at": "2026-05-19T10:00:00Z",
"updated_at": "2026-05-19T10:00:05Z",
"total_rows": 12000,
"created_count": 0,
"updated_count": 0,
"skipped_count": 0,
"deleted_count": 0,
"error_count": 0,
"errors": [],
"error_message": null,
"result": null
}…and again a few seconds later:
{
"job_id": "4242",
"entity": "ARTICLES",
"status": "COMPLETED",
"created_at": "2026-05-19T10:00:00Z",
"updated_at": "2026-05-19T10:00:42Z",
"total_rows": 12000,
"created_count": 9000,
"updated_count": 2950,
"skipped_count": 0,
"deleted_count": 0,
"error_count": 50,
"errors": [
{ "row_number": 137, "identifier": "LEU-0900-18-830", "error_message": "missing list_price" }
],
"error_message": null,
"result": null
}If the whole batch is rejected, nothing is written and the job ends FAILED — error_message carries the reason. A batch rejected for a reason outside its rows, such as an unknown tag name, has no per-row errors[]:
{
"job_id": "4243",
"entity": "ARTICLES",
"status": "FAILED",
"created_at": "2026-05-19T10:05:00Z",
"updated_at": "2026-05-19T10:05:04Z",
"total_rows": 0,
"created_count": 0,
"updated_count": 0,
"skipped_count": 0,
"deleted_count": 0,
"error_count": 0,
"errors": [],
"error_message": "Unknown tag name(s): AE, BR. Create them in the Mercura admin UI before assigning them to articles, or send the batch with create_missing_tags: true.",
"result": null
}When rows themselves are invalid, errors[] lists them as well — see Rejected rows.
result is null for ARTICLES / CUSTOMERS / SUPPLIERS jobs; for REQUESTS jobs (created via POST /tenders / POST /orders) it carries { request_id, request_status, position_count }.