Reject an edge proposal
Reject a proposal: discard it and stop the daemon re-suggesting the pair.
proposal_not_found. The
proposal row is deleted (the same consumption accept performs, minus the edge
write), so it leaves the queue immediately.
REJECTION LEARNING (durable). The same transaction writes the pair —
source node, target node, edge type, for this subject — into the
proposal_rejections ledger, and the daemon’s
GraphService.regenerate_all_proposals excludes rejected pairs (matched in
both directions) from every later pass. So a rejected suggestion does not
come back on the next sleep cycle, and the exclusion survives a re-embed:
the ledger keys on node identity, not on the daemon’s embedding-SHA edge id.
Re-rejecting is idempotent (the first verdict’s timestamp and actor stand),
and accepting the pair later clears the record.
rejectionRecorded in the response reports whether that write happened.
It is false only on a deployment whose tenant schema predates the ledger
(scripts/migrate_public_api_tables.py not yet run): there the reject
still consumes the proposal and still writes its audit row, but the pair may
be re-proposed, exactly as before this feature existed.
Authorization
This route requires thewrite scope.
A missing or invalid credential returns 401 authentication_error. A valid credential without the scope returns 403 permission_denied, and the problem body names the exact scope required.
Headers
These are request conventions the contract does not declare as parameters, so they do not appear in the schema tables below.Success responses
Errors
proposal_not_found, idempotency_in_flight, idempotency_key_reuse. Every problem body names its own code, and the type URI always resolves to the matching page.
Every error is an RFC 9457 application/problem+json body carrying a stable code, a requestId, and a suggestedAction where Exo has one. See Errors.
Notes
- Rejection is a teaching signal.
rejectionRecordedsays whether it was durably stored for the daemon to learn from.
Authorizations
An Exo API key (exo_...) sent as the X-Exo-API-Key header.
Path Parameters
The proposal id from GET /v1/proposals.
Response
Successful Response
The outcome of an accept/reject on a proposal.
decision is accepted or rejected. edgeId is the id of the
edge created by an accept (equal to the proposal id); null on reject.
rejectionRecorded reports whether the reject was written to the durable
rejection ledger, i.e. whether this pair is now permanently excluded from
re-suggestion rather than merely removed from the queue. It is null on
accept (which has nothing to record) and false only on a deployment whose
schema predates the ledger.