---
title: "Update Marketing Consent"
method: PATCH
path: "/api/candidates/{candidate_id}/marketing-consent"
tags: ["Candidates"]
---

# Update Marketing Consent

`PATCH /api/candidates/{candidate_id}/marketing-consent`

## Request

- Base URL: `https://api.ruzora.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.ruzora.com/api/candidates/{candidate_id}/marketing-consent`
- Auth: HTTP bearer

Grant or revoke an engineer's consent to be pitched by MPC.

PRD_MPC_2026-09 M2-4. Before this, `marketing_consent_revoked_at` was
read by the matcher's consent gate and written by NOTHING — a candidate
who asked to stop being pitched could only be honoured by hand-editing
the database. A consent regime with no revoke path is not a consent
regime, and this is the surface Roberto acts on when an engineer asks.

REVOKING NEVER CLEARS THE ORIGINAL GRANT. `marketing_consent_at` stays,
so the record still says what was true: they consented on that date, and
later withdrew it. Blanking the grant would destroy the audit trail that
makes the withdrawal defensible.

REVOCATION IS ONE-WAY HERE. `granted=True` on an already-revoked
candidate is refused with a 409, because re-granting is a decision that
needs the engineer's own new consent, not an operator's PATCH. The
matcher's gate fails closed on the same asymmetry.

## Path parameters

- `candidate_id` string, required

## Request body

- MarketingConsentRequest: `granted=False` revokes. There is no way to spell "un-revoke".
  - `granted` boolean, required
  - `source` string, nullable

## Response `200`

Successful Response

- unknown

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/ruzora/apis/ruzora-candidate-crm-api.md) · [All operations](https://skmtc.dev/ruzora/apis/ruzora-candidate-crm-api/llms.txt) · [OpenAPI document](https://skmtc.dev/ruzora/apis/ruzora-candidate-crm-api/revisions/f9b8223f3ac4?raw)
