Write a note on this domain's timeline
Records the customer's own words against their own timeline — why a policy was published, what a source turned out to be, what to do if the next fortnight goes badly.
The narrowest write on this surface. A note carries text and, at
most, a date. It cannot claim a record changed, cannot set a policy, and
is always stored with origin user: a customer's note appearing on the
timeline as though a detector had observed it would make every other row
on the page less trustworthy.
Requires a user-delegated token. A note records the person who wrote it and the timeline shows their name. A client-credentials token identifies nobody, so this refuses with 422 rather than attributing a sentence to the organization and leaving the next reader with nobody to ask. Same rule as recording a source decision.
Returns the whole timeline, folded, so the caller renders the new note in the company of the events it sits between rather than appending it to a list that has not been through the same grouping.
Path parameters
domain string required The domain, by NAME (acme.com). A UUID is also accepted. Matched case-insensitively, and scoped to the calling org — a domain belonging to another org is a 404, never a 403.
Request body
Content type: application/json
note string required The text. Required and trimmed.
Constraints: length 0–2000
occurred_at string<date-time> optional Optionally back-date the note. Annotating a change you made last week is a legitimate use of a timeline, and the alternative is a note sitting three days away from the event it describes. Omitted, the note is dated to when it was written — which for a person IS the evidence.
Responses
Errors follow the RFC 7807 problem format — see the error reference.
events array<object> required Each entry in events:
id string<uuid> required The ANCHOR sighting's annotation id — a row that really exists, not a synthetic identifier.
kind string enum required policy_change moved the published p= or sp=. setup_change is a record edit that did NOT move the policy — a rewritten rua tag, a new reporting address — and it is a separate kind rather than a variant because it is how reporting silently stops, which is the commonest way a healthy domain becomes an unmonitored one.
One of: policy_change, setup_change, source_decisions, acknowledgement, note
anchor_origin string enum required Which sighting supplied occurred_at and the record text. The dns sighting wins whenever there is one: its timestamp comes from a poll that either saw the record or did not, where the report-derived one is a day bucket assembled from mail receivers had already judged.
One of: dns, reports, user, system
occurred_at string<date-time> required observed_at string<date-time> required The EARLIEST observation across the sightings — when we first knew.
old_policy string enum required The p= before the change. "" means no policy was published — a real prior state, not a missing value, and the state a first publish moves out of.
One of: ``, none, quarantine, reject
new_policy string enum required One of: ``, none, quarantine, reject
old_record string required The _dmarc TXT before the change, verbatim as observed. Empty when no sighting carried record text — the ordinary state of a change only the reports saw.
new_record string required The _dmarc TXT after the change, verbatim as observed.
tightening boolean required Whether this was a move UP the ladder. Always false for a setup_change however much of the record it altered: a rua rewrite is not a rung, and treating one as a rung would put a domain into a fourteen-day watch window for an edit receivers do not act on.
Derived here rather than left to the caller, because re-deriving it from the two policy fields means reproducing the rule that an absent record ranks BELOW none — and a caller who misses that gets both the first publish and the total loss of a record backwards.
weakening boolean required A move DOWN the ladder, including a record that disappeared entirely — which is the worst version of it and the one nothing else in the product can see.
note string optional The customer's own text, for a note event.
sightings array<object> required The annotations behind this event, oldest first. Always at least one.
Each entry in sightings:
annotation_id string<uuid> required The stored row.
origin string enum required Where the fact came from. dns is a live lookup of the published record: exact text, a tight timestamp, and it describes only the moment of the poll. reports is reconstructed from the policy receivers said they applied: it lags 24-48 hours, is coarse to the day, and is the ONLY origin that can describe a change made before the domain was onboarded. user is a person. system is us.
One of: dns, reports, user, system
occurred_at string<date-time> required When the thing happened, read from this sighting's evidence.
observed_at string<date-time> required When SendOps noticed. Differs from occurred_at by 24-48 hours whenever the evidence is a DMARC report, and reading the second as the first would place a policy change after mail that was already judged under it.
has_record_text boolean required Whether this sighting carried the _dmarc TXT either side. Always false for a report-derived sighting: receivers report the policy they applied, never the record that set it.
annotations integer required How many stored rows the events were folded from. Reported beside the event count rather than left implicit, so a caller can see the folding happened: 12 annotations, 7 events is the difference between a domain both detectors watch and one only the reports reach.
code is internal_error. The
request_id field can be quoted to SendOps support to investigate.
application/problem+json