# Public Tenders Create

Create a tender from uploaded files (async processing).
The programmatic twin of forwarding an LV / RFQ email to
`anfragen@lv.mercura.ai`: Mercura stores the files, picks the file
that drives parsing (GAEB before spreadsheet/CSV/DOCX/TXT before PDF
before image), extracts chapters and positions, matches them against
your catalogue, and lands the tender ready for review.
**Response.**
- `202 Accepted` with `JobAck { job_id, status_url }` on the first
call.
- `200 OK` with the *same* `JobAck` on an idempotent replay (same
`Idempotency-Key` + same form fields and file contents).

**What to do next.** Poll `GET /jobs/{job_id}` until `status` is
`COMPLETED` or `FAILED` (the terminal state is reached when
*processing* finishes, not when the upload is accepted), or subscribe
to the `request.processing_completed` webhook and correlate by
`job_id`. The resulting offer is then readable via `GET /tenders`.
**Correlating with your system.** Use `custom_fields` to carry your
own identifier (a CRM case number, an ERP reference) onto the tender at
creation time, and `branch` to route it. Both are validated against
your organisation's configuration *before* the job is created, so a
typo fails fast instead of landing an unidentifiable tender. Store the
`request_id` from `GET /jobs/{job_id}` on your side — it is the
stable handle for every later call (`GET`/`PATCH /tenders`).
**Idempotency.** Pass an `Idempotency-Key` header (≤ 255 chars). Same
key with a *different* body returns `422 IDEMPOTENCY_KEY_MISMATCH`.

Endpoint: POST /tenders
Version: 1.33.0

## Header parameters:

  - `authorization` (string | null)
    Bearer <mrc_live_…> API key

  - `Idempotency-Key` (string | null)
    Optional client-supplied key for safe retries; <= 255 chars

## Request fields (multipart/form-data):

  - `files` (array, required)
    One or more files, exactly as you would attach them to a forwarded email: GAEB (.d81/.d83/.d94/.p81/.p83/.p93/.p94/.x81/.x83/.x93/.x94/.onlv), .xlsx, .csv, .docx, .txt, .pdf, images (.png/.jpg/.jpeg/.gif/.bmp/.tiff/.webp), and .eml. Max 50 MB per file, 100 MB total, 20 files.

  - `name` (string | null)
    Display name for the tender in Mercura (the email channel uses the subject line). Defaults to the primary file's name.

  - `customer_id` (string | null)
    Your customer id — the same identifier the customers resource exposes as `customer_id`. Takes precedence over customer_email. An unknown id is not an error — the tender is created without a customer, exactly like an email from an unknown sender.

  - `customer_email` (string | null)
    Customer contact email, matched with the same rules the email channel applies to the sender address (exact contact match, domain pattern, unique inferred domain).

  - `context` (string | null)
    Free-text context that helps Mercura process the tender — e.g. the original email body, the kind of request, delivery notes, or guidance for article matching.

  - `branch` (string | null)
    Name of the Mercura branch (Niederlassung) this tender belongs to — exactly as it is configured in Mercura, matched case-insensitively. Routes the tender to the team that works that branch. An unknown name is a `400`: an unrouted tender is worse than a rejected upload.

  - `custom_fields` (string | null)
    JSON object of organisation-defined custom fields to stamp on the tender, keyed by the field's display **label** — e.g. `{"Case Number": "00012345"}`. The same labels the read side emits in `request_custom_fields`, so a value set here comes back unchanged on `GET /tenders/{tender_id}`. Unknown labels are a `400`.

## Response 200 fields (application/json):

  - `job_id` (string, required)

  - `status_url` (string, required)
    Relative URL to poll for this job's status

