- Reading tenders
Creating a tender
Carrying your own reference and routing
Line order
Removed lines and positions
The complete Leistungsverzeichnis
Review notes (
Tender documents
Document feed
Editing a tender
Closing a tender
Acknowledging a tender
Reporting lifecycle events
Completion feed
Export file
Public Tenders Create
Public Tenders List
Public Tenders Document Feed
Public Tenders Get
Public Tenders Update
Public Tenders List Documents
Public Tenders Get File
Public Tenders Acknowledge
Public Tenders Record Event
Reading tenders
A tender is keyed by the request id (tender_id == request_id): reading one returns the tender's current projected state — the structured, priced result Mercura produces — carrying everything on the corresponding PDF the customer sees:
status— lifecycle state (NEW,IN_PROGRESS,DONE,CANCELLED,PARSING,PARSING_FAILED).DONEmeans the tender has been completed (released to the partner API via the seller's Finalize / Export → API action — which is what stampscompleted_atand firestender.completed).completed_at— when the tender was last completed, ornullif it never was. Refreshed on every completion, so a re-export moves it forward (see the completion feed below).customer_id— the direct customer (Sold-To) reference only (yourBusinessPartner.external_id); resolve name / address / contact / custom fields viaGET /customers/{customer_id}. Null when the tender has no customer.indirect_customer_id— the indirect customer (Mercura's indirekter Kunde) reference only; resolve the full record viaGET /customers/{customer_id}. Distinct fromcustomer_id. Null when the tender has no indirect customer.project_id— the project reference only; resolve the full record viaGET /projects/{project_id}. Null when the tender has no project.project_name— the project's display name, surfaced inline (same value asnameonGET /projects/{project_id}) so you need no second call. Null when the tender has no project.object_number— your object number (Objektnummer) for this tender: the identifier your ERP opens the job under, surfaced inline so you need no second call. It is the tender's own number when one is maintained — an ERP that opens one object per incoming tender gives sibling tenders on the same project different numbers — otherwise the project'sobject_number.nullwhen neither carries one. Read-only here: Mercura users maintain it in the app, andPOST /projects/{project_id}/acknowledgementswrites the project-level one (see the Projects tag).submission_date— the bid-submission date (Submissions-/Abgabetermin) as originally supplied on the project: an ISO date or free text,nullwhen unknown. This is the tender's submission deadline, not an offer-validity (gültig bis) date. Mirrors the project'ssubmission_date.deadline— Mercura's internal handling deadline for the request (typically the submission date minus a buffer): an ISO date or free text,nullwhen unset. Informational only — not the submission deadline and not an offer-validity date.user_email— the responsible Mercura user for the tender (mirrors the integration-exportuser_email).branch— the primary Mercura branch (Niederlassung) assigned to the tender as{ id, name }, ornullwhen none is assigned.request_custom_fields— custom fields on the underlying request, keyed by display label (multi_selectvalues resolved to their option labels). Writable onPATCH(see Editing a tender).user_custom_fields— custom fields on the responsible user (user_email), keyed by display label — e.g. a user'sSGI.nullwhen the tender has no responsible user or the user has no custom fields. (You can still resolve the same fields viaGET /users?email={user_email}.)export_fields— what the user entered in the ERP export dialog when releasing the tender: your organisation's own export fields (e.g. the customer or ship-to number to book the offer under), keyed by the field key configured for your organisation. Reflects the latest release through that dialog;nullwhen there was none or your organisation configures no such fields. Read-only.chapters[]— the title tree. Each chapter carries anid,chapter_number,name,is_pretext(a Vorbemerkung),sequence, nestedchapters[], andpositions[].positions[](per chapter) — one entry per line, each with:id— an opaque, re-match-stable handle (the position's request-scoped number); the key you pass back to edit the line.line_type—ARTICLE/TEXT/DIVERSE.labels[]— role/label overlay, each{ text, type }(typeisCUSTOM/ALTERNATIVE/ACCESSORY/PARTS_LIST); aCUSTOMlabel carries your org-defined text (product groups, "Bestellware", …). OnPATCHit is writable in exactly one place — marking a new sub-line as an alternative or an accessory (see Editing a tender); on an edit it is ignored, so a GET body round-trips.gaeb_position_type— the GAEB Positionsart (BASE,OPTIONAL_WITH_TOTAL,OPTIONAL_WITHOUT_TOTAL,ALTERNATIVE) or null.article_number,manufacturer_article_number,name,description,additional_text,quantity,unit,list_price,discount_percentage,net_price,line_net,line_gross.parent_line_id— set only on an article-note line: theidof the line it annotates (both sit on the same position). Null everywhere else.name— the matched article's name: the article text maintained in Mercura (the title shown in the UI). Null for a free-text line.description— the matched article's owndescriptionfield (distinct fromname), or the free-text for a text line.description_lines—descriptionsplit into its lines (trailing whitespace and trailing empty lines dropped), for an ERP that keeps a line's text as fixed-length rows, e.g. SAP's two 40-character rows. Your organisation can have the text of DIVERSE lines entered as a fixed number of rows of a maximum length; each row then arrives as typed. Read-only.specification_text— the source LV's own long text for this ordinal number (the Ausschreibungstext, verbatim), independent of what Mercura matched to it and identical on every line sharing aposition_number. Use this — notdescription— when you import the Leistungsverzeichnis itself rather than the priced offer. Null when the source LV carried no long text.page_number— the 1-based page of the source document this ordinal number was read from, identical on every line sharing aposition_number. Use it when the request document refers to its items by page rather than by number, e.g. to group your quote lines by page. It counts the pages of the file as Mercura received it; it is not a page label printed on the page. Null when no page is known (GAEB and other structured files, positions added by hand). Not part of theETag; ignored onPATCH.manufacturer— the matched article's manufacturer / supplier name (Hersteller/Lieferant), or null for a free-text line.custom_attributes— the matched article's catalogue custom attributes (same shape asGET /articles/{id}'scustom_attributes, e.g.sales_unit, the article typearticle_type, and other source-system unit/extra fields), or null for a free-text line.- For a
DIVERSEline matched to a generic "Divers" placeholder article,descriptionis the operator-typed text (what you see in the matching UI), not the placeholder article's catalogue text. is_counted_in_total— false for lines excluded from the totals (alternatives, Bedarfsposition ohne Gesamtbetrag).partner_pricing_override_at— when a partner last overrode the line's price via PATCH, else null.is_deleted/deleted_at— whether this line was removed from the tender, and when. Only ever set when you ask for removed lines (include_deleted=true, see Removed lines and positions).is_lv_only— true for an ordinal number that carries no priced line at all. Only ever set when you ask for the whole LV (include_all_positions=true, see The complete Leistungsverzeichnis).sequence— where the line stands in Mercura's order (see Line order).
totals—positions_subtotal,additional_discount_percentage,net_total,gross_total(EUR), andpartner_totals_override_at.positions_subtotalis a derived helper: the sum across lines withis_counted_in_total = true(excludes alternatives and Bedarfspositionen ohne Gesamtbetrag).net_total/gross_totalare the authoritative amounts that match the PDF — they are after the header discount and may include optional positions or other adjustments, so they can legitimately differ frompositions_subtotal. Treatnet_totalas the amount owed.erp_offer_id— the partner-side ERP offer id when known (populated from your acknowledgement'sexternal_id, or from a Mercura-managed ERP export).acknowledgement— your last reported import outcome for this tender (status,external_id,message,metadata,acknowledged_at), ornulluntil you acknowledge it (see below).
You can:
GET /tenders— cursor-paginated list. Usemodified_sincefor delta-sync catch-up scans, orstatusto filter by lifecycle state.GET /tenders/{tender_id}— one tender in full. This is what thetender.completedwebhook points you at. The response carries a strongETagover the tender content; pass it back asIf-Matchon PATCH.