PATCH /projects/{project_id} writes back the fields your ERP owns. The canonical use is reconciling identifiers: your ERP creates a project / commission number and PATCHes it into object_number so every later tender.completed / order.completed webhook and GET /projects lines up with your own key.
Writable fields (all optional): object_number, name, status, estimated_value, currency, submission_date, custom_fields.
If object_number is the only field you need to write, you can skip PATCH entirely and send it as the external_id of an acknowledgement instead — see Acknowledging a project.
Semantics:
- Partial. Send only what you change. An omitted field is left untouched; an explicit
nullclears that field.statusis the one exception — it cannot benull(a project always has a lifecycle state), and an unknown status value is a400. object_numberis a grouping key. Mercura derives the master-project grouping from this value at read time, so writing it simply moves the one project row you addressed into (or out of) a group — sibling rows that shared the old value are not rewritten.custom_fieldsis label-keyed and shallow-merged. Use the same labels you receive onGET(and, for a multi-select, the same option labels). Keys you include are set; a key mapped tonullclears that one field; keys you omit are left as they are. An unknown label — or an unknown option label on a multi-select — returns400 VALIDATION_FAILEDnaming the offending keys, so a typo fails loudly instead of silently writing nothing.
Optimistic concurrency: read the project first, then echo the ETag you received as an If-Match header on the PATCH. If someone else changed the project in the meantime the ETag no longer matches and the request is rejected with 412 Precondition Failed — re-fetch and retry. Omit If-Match (or send If-Match: *) to skip the check. A no-op edit (an empty body, or values equal to the current ones) does not advance the project's updated_at.
PATCH /projects/90 HTTP/1.1
Authorization: Bearer <your-api-key>
If-Match: "3f8b6d21..."
Content-Type: application/json
{
"object_number": "P-2026-00417",
"status": "CUSTOMER_WON_AWARDED_TO_US",
"custom_fields": { "ERP-Auftragsnummer": "SO-88231" }
}