Patch DDS Config
Apply incremental changes to a dds_record's exclusion +
justification config — without touching plots you don't mention.
Useful when iterating on a review: add one exclusion, drop another,
bump a justification text, attach an extra evidence URL — without
having to resend the full state every time.
Note — compliance verdict overrides: this bulk endpoint does not accept
compliance_overrideonset_justifications. For verdict overrides use the per-plot Set Verdict Override endpoint, which writes the override + narrative + audit reason in a single PUT. Updates here that touch a plot's justification text leave any existing override on the row untouched (preserve semantics).
▶Path params
| Param | Description |
|---|---|
recordId | DDS record id |
▶Request body
Every key is optional, but at least one must be set (else 400).
{
"set_justifications": {
"<plot-uuid>": { "text": "max 5000 chars" }
},
"remove_justifications": ["uuid", ...], // drop these justifications entirely
"add_evidence_urls": {
"<plot-uuid>": ["https://...", ...] // append (deduped) per plot
},
"remove_evidence_urls": {
"<plot-uuid>": ["https://...", ...] // remove specific URLs per plot
}
}
▶Operation order (within one PATCH)
Operations run in a single transaction. Order is fixed so a caller can swap roles within the same request:
remove_justifications→ justification rows deleted (this also drops anycompliance_overrideon the row)set_justifications→ justifications upserted (insert or updatetext). On update, any existingcompliance_overrideon the row is preserved untouched; on insert, the new row'scompliance_overridedefaults tonull. Use PUT /verdict-overrides (axisplot_compliance) to set, change or clear the override. That endpoint is a FULL replace — it writes the finding row you send, so include every field you want to keep.- Per plot in
add_evidence_urls∪remove_evidence_urls: read existing array → dropremoveURLs → appendaddURLs (deduped) → write back
Adding an exclusion that's already present, removing one that isn't, or setting a justification with the same text are all idempotent — re-sending the same PATCH is safe.
▶Validation rules
- Visibility: 404 when the record's
organization_idisn't in the caller'seffectiveOrgIds. - Plot membership: every UUID in any of the body fields must appear in the record's current version snapshot. The union across all six fields is checked in one pass; the 400 response lists the offending ids.
- At least one operation: empty body →
400 BAD_REQUEST. - Evidence URLs require a justification:
add_evidence_urlsorremove_evidence_urlsfor a plot that has no justification is a silent no-op. Set the justification first (or in the same PATCH) for the URLs to land.
▶Response (200)
Returns the full post-mutation config state — the current
exclude_plots array and justifications map (each entry with
text, evidence_urls, and compliance_override) for the
record's current version.
add_excluded/remove_excludedwere removed (EPO-1983). An exclusion is now a finding, so usePUT/DELETE /verdict-overrideswithaxis: "exclusion". They are refused by name with a 400 rather than silently dropped: this body is not.strict(), so an ignoredadd_excludedpaired with a justification edit would answer 200 having done half the work, and the caller would file a record still holding the plot they believed they had excluded.
▶Errors
| Status | Code | When |
|---|---|---|
| 400 | BAD_REQUEST | Empty body, body failed Zod validation, or a referenced plot id is outside the record's current version |
| 401 | UNAUTHORIZED | Missing/invalid API key |
| 404 | NOT_FOUND | Record isn't visible to the caller |
Required scope:
ingestions:write