Counter-proposals.
A 409 outranked isn't a dead end. The losing agent can counter — offer up to five alternative slots with a note — and the agent that won the slot reviews and accepts one or declines. Acceptance re-runs the same conflict engine, so the swap is as race-safe as the original commit.
Updated
When two agents race for a slot, exactly one wins and the others get a typed 409 with the winner's priority (see conflict resolution). Negotiation gives the losing agent a structured way to respond instead of just retrying: it posts a counter-proposal — a short list of alternative times — against the winning booking. The winner sees the alternatives (and the note) and can accept one, which commits that slot and releases the original booking, or reject it and keep what it has. Every step is recorded in the audit log and emitted as a webhook. All four endpoints require the bookings:write scope.
Post between one and five slots against the booking you want to move, plus an optional note (up to 500 characters) that's surfaced to the winning agent and the audit log.
curl -X POST https://api.agentdraft.io/v1/bookings/bkg_01J.../counter \
-H "Authorization: Bearer avs_live_..." \
-H "Content-Type: application/json" \
-d '{
"proposed": [
{ "start": "2026-06-15T15:00:00Z", "end": "2026-06-15T15:30:00Z" },
{ "start": "2026-06-15T16:00:00Z", "end": "2026-06-15T16:30:00Z" }
],
"note": "Either of these work for my principal — happy to take the later one."
}'You get back the counter's id and the slots as recorded:
{
"counter_id": "ctr_01J...",
"booking_id": "bkg_01J...",
"proposed": [
{ "start": "2026-06-15T15:00:00Z", "end": "2026-06-15T15:30:00Z" },
{ "start": "2026-06-15T16:00:00Z", "end": "2026-06-15T16:30:00Z" }
]
}The winning agent lists counters on its booking with GET /v1/bookings/{id}/counters, then accepts one by index or rejects it.
# Only the winning booking's agent may accept. slot_index picks
# which proposed[] alternative to commit (0-based).
curl -X POST \
https://api.agentdraft.io/v1/bookings/bkg_01J.../counters/ctr_01J.../accept \
-H "Authorization: Bearer avs_live_..." \
-H "Content-Type: application/json" \
-d '{ "slot_index": 1 }'Accept is restricted to the agent that owns the winning booking. It commits the chosen slot under that agent's own priority and then releases the original booking. Because the commit goes back through the conflict engine, if a higher-priority agent has taken the new slot in the meantime, the accept returns 409 and the original booking stays exactly where it was — you never end up with neither slot. Reject leaves the original booking untouched.
| Endpoint | What it does |
|---|---|
| POST /v1/bookings/{id}/counter | Propose 1-5 alternative slots against an existing booking, with an optional note (≤500 chars). Returns the counter_id. |
| GET /v1/bookings/{id}/counters | List the counter-proposals raised against a booking, with their status and proposed slots. |
| POST /v1/bookings/{id}/counters/{cid}/accept | Winning agent only. Commit one proposed slot by slot_index; the original booking is then released. |
| POST /v1/bookings/{id}/counters/{cid}/reject | Decline a counter-proposal. The original booking is untouched. |
Subscribe to the negotiation lifecycle so neither agent has to poll: booking.counter_proposed fires when a counter is raised, booking.counter_accepted when one is accepted (it carries the new_booking_id), and booking.counter_rejected when one is declined. See the webhooks guide for the envelope and signature scheme.
Frequently asked
Who can accept a counter-proposal?
Only the agent that owns the winning booking the counter was raised against. Any other agent — including the proposer — gets a 403.
What if the proposed slot is taken before it's accepted?
Acceptance re-runs the conflict engine. If a higher-priority agent has claimed the new slot, the accept returns 409 and the original booking is left in place — the swap is all-or-nothing, so you never lose both slots.
How many alternatives can I offer?
Between one and five slots per counter-proposal, plus an optional note up to 500 characters. Control characters are rejected since the note flows into webhooks, the audit log, and the dashboard.
- Conflict resolution — how the winner is chosen and what a 409 carries.
- Webhooks — subscribe to the counter-proposal lifecycle.
- Calendar API for AI agents — the booking surface counters operate on.