eva crm Public API
Appointments

Book an appointment

POST /v1/appointments — book on a lead, a contract or nothing, with the CRM's duplicate and clash checks.

POST Book an appointment

POST/v1/appointments

Books an appointment through the CRM's own writer, so everything that happens when staff book happens here too: notifications to the people it is for, and on a lead the sales person or surveyor, the sales date and the workflow's appointed event, which may move the lead's stage exactly as booking in the CRM would.

Request bodyapplication/json
typestring · name, value or idRequired
startstring · date or date-timeRequired

In your timezone unless it carries an offset.

endstring · date or date-time

Not with durationMinutes. Neither means one hour.

durationMinutesinteger · 5 to 1440

Not with end.

Default: 60
allDayboolean

Covers whole calendar days; the times in start and end are ignored.

Default: false
statusstring

Confirmed needs at least one user or team, as in the CRM.

Valid values: provisional, confirmed
Default: provisional
usersstring[] · max 20

Who it is for, by user id or email. Neither users nor teams books it unassigned.

teamsstring[] · max 10

Teams by id or name. May be sent together with users.

leadIdstring · uuid

The lead it belongs to. Not with contractId. Neither makes a plain diary entry.

contractIdstring · uuid

The contract it belongs to.

titlestring · max 255

Left out, the CRM's own is generated: postcode and surname for a sales visit on a lead, otherwise the type and who it is for.

descriptionstring · max 2000
locationstring · max 500

Left out, the record's contact address is used.

forceboolean

Book even when the checks below would refuse.

Default: false

The CRM's checks

Before writing, the two checks the CRM's booking form runs. Send force: true to book anyway, as staff can in the CRM. Cancelled appointments never block.

  • The customer already has one. Another appointment for the same customer on the same kind of record overlaps the window.
  • Someone is already booked. A user or team on this appointment has an overlapping appointment that is not cancelled. Availability shows where they are free.
Responses
201
The appointment, as GET shows it.
404
No such lead or contract.
409
The customer already has an appointment in that window (`fields.start`), or someone on it is already booked (`fields.users`).
422
A field is wrong, confirmed with nobody on it, or a confirmed Fitting on a contract whose workflow stage does not allow confirming fittings — as in the CRM. `fields` names it.
502
The CRM did not answer. Nothing was booked; repeat the request.
Example request
curl https://api.evacrm.co.uk/v1/appointments \
  -H "Authorization: Bearer sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "type": "Sales",
    "start": "2026-10-13T10:00",
    "durationMinutes": 60,
    "users": ["jo@example.com"],
    "leadId": "8bd8e096-dd31-44cf-8373-3a00db14dfd3",
    "description": "Customer asked for a morning visit"
  }'
Example response · 201
{
  "id": "cff5e8d2-bd17-4546-bbc6-0376a41596c3",
  "title": "NN4 8LN - Smith",
  "eventName": null,
  "description": "Customer asked for a morning visit",
  "location": "6 Briar Hill Walk Northampton NN4 8LN",
  "type": { "id": "ab6e78a0-4e85-405f-ba19-4753beac8445", "name": "Sales", "value": "sales" },
  "status": "provisional",
  "outcome": null,
  "start": "2026-10-13T10:00:00.000+01:00",
  "end": "2026-10-13T11:00:00.000+01:00",
  "allDay": false,
  "participants": [{ "kind": "user", "id": "50f716dc-c202-4d27-bc60-a1697533e03b", "name": "Jo Savant", "email": "jo@example.com" }],
  "linkedTo": { "kind": "lead", "id": "8bd8e096-dd31-44cf-8373-3a00db14dfd3", "code": "L013885" },
  "locked": false,
  "createdBy": { "id": "cd9356b7-dd81-4f9a-a6fd-9cc9ae967a4e", "name": "Tuan Dinh" },
  "createdAt": "2026-10-01T14:14:54.527+01:00",
  "updatedAt": "2026-10-01T14:14:54.527+01:00"
}

Cancelling, rescheduling and editing are not available yet; do those in the CRM.

On this page