API

API reference

Every route of the Kwazi REST API, with its parameters, permissions and matching ability.

Kwazi 1.0.0. Base URL: https://your-site.example/wp-json/kwazi/v1 (authentication). The OpenAPI document of your own site (GET /openapi.json) also lists your custom fields under ContactFields and OrganizationFields.

Audit log

GET /audit-log — Find audit log entries

Lists the audit log, newest first: who did what through which channel (app, API key, AI agent, system), with the key or agent by name. Kept 12 months. Returns at most limit items and a next_cursor.

Permission: kwazi_manage_integrations · Ability: kwazi/find-audit-entries

Parameter In Type Required Description
channel query string (app, portal, api, ability, form, booking, import, email, system) no
action query string (max. 60) no
cursor query string (max. 64) no
per_page query integer (1–100) no

Answers: 200: items, next_cursor, total. Errors: error shape.

Booking (public)

POST /booking/book — Book an appointment as a website visitor (honeypot, time token, rate limit).

Public: no login (website visitors).

Answers: 201. Errors: error shape.

POST /booking/manage — Open an appointment with the token from its manage link.

Public: no login (website visitors).

Answers: 200. Errors: error shape.

POST /booking/manage/cancel — Cancel an appointment with the token from its manage link.

Public: no login (website visitors).

Answers: 200. Errors: error shape.

POST /booking/manage/reschedule — Move an appointment with the token from its manage link.

Public: no login (website visitors).

Answers: 200. Errors: error shape.

GET /booking/services — Services that can be booked online, for the booking widget.

Public: no login (website visitors).

Answers: 200. Errors: error shape.

GET /booking/slots — Free times of a service, for the booking widget.

Public: no login (website visitors).

Parameter In Type Required Description
service query string (uuid) yes
staff query integer (1–) no
from query string no
to query string no

Answers: 200. Errors: error shape.

Booking: appointments

GET /appointments — Find appointments

Lists appointments with their client: in a period of local days (from, to; at most 62 days) and/or of one contact (contact id), by start time; or everything changed since a moment (updated_since) in pages of limit with a next_cursor. Optionally one staff member (user id) and statuses (pending, confirmed, declined, cancelled, completed, no_show). With "only own" visibility a staff member only gets their own calendar.

Permission: kwazi_view_contacts · Ability: kwazi/find-appointments

Parameter In Type Required Description
from query string no
to query string no
staff query integer (1–) no
status query array of string (pending, confirmed, declined, cancelled, completed, no_show, pending_payment) no
contact query string (uuid) no
updated_since query string (date-time) no Polling: appointments changed at or after this moment (ISO 8601), in pages with per_page and cursor.
per_page query integer (1–100) no
cursor query string (max. 64) no

Answers: 200: items, next_cursor, total. Errors: error shape.

POST /appointments — Book an appointment

Books an appointment for a contact at a free start time from kwazi/get-available-slots. Without staff the least busy free staff member gets it. If the time was taken meanwhile, the error lists the nearest free times.

Permission: kwazi_manage_bookings · Ability: kwazi/book-appointment

Body field Type Description
contact string (uuid)
service string (uuid)
staff integer or null
starts_at string (date-time) ISO 8601 with a time zone, e.g. 2026-10-19T08:00:00Z.
notes string (max. 2000)
outside_hours boolean Book outside working hours on purpose (never over another appointment).
location_type string (in_person, client, phone, online)
location string (max. 255)
meeting_url string (max. 2048)
status string (confirmed, pending)

Answers: 201: id, status, service, staff, contact, starts_at, ends_at, location, meeting_url, notes, source, submission, cancel_reason, created_at, updated_at. Errors: error shape.

GET /appointments/{id} — Get an appointment

Returns one appointment with its service, staff member, client (name, email, phone), time, place and status.

Permission: kwazi_view_contacts · Ability: kwazi/get-appointment

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200: id, status, service, staff, contact, starts_at, ends_at, location, meeting_url, notes, source, submission, cancel_reason, created_at, updated_at. Errors: error shape.

PATCH /appointments/{id} — Update the note of an appointment

Replaces the internal note of an appointment (for the team only, never shown to the client).

Permission: kwazi_manage_bookings · Ability: kwazi/update-appointment-note

Parameter In Type Required Description
id path string (uuid) yes
Body field Type Description
notes string (max. 2000)

Answers: 200: id, status, service, staff, contact, starts_at, ends_at, location, meeting_url, notes, source, submission, cancel_reason, created_at, updated_at. Errors: error shape.

POST /appointments/{id}/cancel — Cancel an appointment

Cancels an appointment that is pending or confirmed. The client gets an email (and a calendar cancellation); the reason is internal and never sent to the client. It cannot be undone: book again if needed.

Permission: kwazi_manage_bookings · Ability: kwazi/cancel-appointment

Parameter In Type Required Description
id path string (uuid) yes
Body field Type Description
reason string (max. 500)

Answers: 200: id, status, service, staff, contact, starts_at, ends_at, location, meeting_url, notes, source, submission, cancel_reason, created_at, updated_at. Errors: error shape.

POST /appointments/{id}/complete — Mark an appointment as completed

Marks an appointment that has started as completed. No email is sent.

Permission: kwazi_manage_bookings · Ability: kwazi/complete-appointment

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200: id, status, service, staff, contact, starts_at, ends_at, location, meeting_url, notes, source, submission, cancel_reason, created_at, updated_at. Errors: error shape.

POST /appointments/{id}/confirm — Confirm an appointment request

Confirms an appointment that waits for confirmation (status pending). The client gets an email with a calendar file and a link to cancel or move.

Permission: kwazi_manage_bookings · Ability: kwazi/confirm-appointment

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200: id, status, service, staff, contact, starts_at, ends_at, location, meeting_url, notes, source, submission, cancel_reason, created_at, updated_at. Errors: error shape.

POST /appointments/{id}/decline — Decline an appointment request

Declines an appointment that waits for confirmation. The time is free again and the client gets an email; the reason is internal and never sent to the client.

Permission: kwazi_manage_bookings · Ability: kwazi/decline-appointment

Parameter In Type Required Description
id path string (uuid) yes
Body field Type Description
reason string (max. 500)

Answers: 200: id, status, service, staff, contact, starts_at, ends_at, location, meeting_url, notes, source, submission, cancel_reason, created_at, updated_at. Errors: error shape.

POST /appointments/{id}/no-show — Mark an appointment as no-show

Marks that the client did not come to an appointment that has started. No email is sent.

Permission: kwazi_manage_bookings · Ability: kwazi/mark-no-show

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200: id, status, service, staff, contact, starts_at, ends_at, location, meeting_url, notes, source, submission, cancel_reason, created_at, updated_at. Errors: error shape.

POST /appointments/{id}/place — Change where an appointment takes place

Changes the place of a pending or confirmed appointment: location_type in_person (location = address; empty = the address of the service), client (location = the client’s address, required), phone (the client’s phone number) or online (meeting_url, http/https; empty = the staff member’s link). The client gets an email with the new place, a calendar file once confirmed and a new manage link.

Permission: kwazi_manage_bookings · Ability: kwazi/change-appointment-place

Parameter In Type Required Description
id path string (uuid) yes
Body field Type Description
location_type string (in_person, client, phone, online)
location string (max. 255)
meeting_url string (max. 2048)

Answers: 200: id, status, service, staff, contact, starts_at, ends_at, location, meeting_url, notes, source, submission, cancel_reason, created_at, updated_at. Errors: error shape.

POST /appointments/{id}/reschedule — Move an appointment

Moves an appointment to another free time (starts_at, ISO 8601 with time zone; see kwazi/get-available-slots) and optionally another staff member (user id). outside_hours: true allows a time outside working hours, never over another appointment. The client gets an email with the new time and a new manage link.

Permission: kwazi_manage_bookings · Ability: kwazi/reschedule-appointment

Parameter In Type Required Description
id path string (uuid) yes
Body field Type Description
starts_at string (date-time)
staff integer (1–)
outside_hours boolean

Answers: 200: id, status, service, staff, contact, starts_at, ends_at, location, meeting_url, notes, source, submission, cancel_reason, created_at, updated_at. Errors: error shape.

GET /calendar — Get the calendar

Returns per staff member the working hours of each day (after time off, closures and extra hours) and the appointments that are not cancelled or declined, for local days from..to (at most 62 days). Use it to see who is free or busy on a day.

Permission: kwazi_view_contacts · Ability: kwazi/get-calendar

Parameter In Type Required Description
from query string no
to query string no
staff query integer (1–) no

Answers: 200: timezone, staff, appointments. Errors: error shape.

GET /slots — Get free times

Lists free start times (ISO 8601 UTC) for a service between two local days (at most 62 days apart), with the staff members free at each. Leave staff out for anyone who does the service.

Permission: kwazi_view_contacts · Ability: kwazi/get-available-slots

Parameter In Type Required Description
service query string (uuid) yes
staff query integer (1–) no
from query string no
to query string no

Answers: 200. Errors: error shape.

Booking: services

GET /services — List services

Lists the bookable services: length, buffers, price (shown only), location (in_person, client, phone, online), confirmation (auto or review) and the user ids of the staff who do them.

Permission: kwazi_view_contacts · Ability: kwazi/list-services

Parameter In Type Required Description
include_archived query boolean no

Answers: 200. Errors: error shape.

POST /services — Create a service

Creates a bookable service. name and duration_min are required; staff lists the user ids who do it.

Permission: kwazi_manage_crm · Ability: kwazi/create-service

Body field Type Description
name string (max. 190)
description string (max. 2000)
duration_min integer (1–1440)
buffer_before integer (0–) Minutes kept free before, only against other appointments; not shown to clients.
buffer_after integer (0–)
price string or null For example "45" or "45.50"; shown only.
location_type string (in_person, client, phone, online)
location_details string (max. 255)
confirmation string (auto, review) auto confirms online bookings at once; review keeps them pending until the team confirms.
bookable_online boolean
min_notice_min integer or null
max_advance_days integer or null
sort_order integer
staff array of integer WordPress user ids of the staff members who do it (see kwazi/list-staff).

Answers: 201: id, name, description, duration_min, buffer_before, buffer_after, price, location_type, location_details, confirmation, bookable_online, min_notice_min, max_advance_days, form_id, sort_order, staff, archived, created_at, updated_at. Errors: error shape.

GET /services/{id} — Get a service

Returns one service, also when it is archived.

Permission: kwazi_view_contacts · Ability: kwazi/get-service

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200: id, name, description, duration_min, buffer_before, buffer_after, price, location_type, location_details, confirmation, bookable_online, min_notice_min, max_advance_days, form_id, sort_order, staff, archived, created_at, updated_at. Errors: error shape.

PATCH /services/{id} — Update a service

Changes the given settings of a service; archived: false brings an archived service back. Existing appointments keep what they were booked with.

Permission: kwazi_manage_crm · Ability: kwazi/update-service

Parameter In Type Required Description
id path string (uuid) yes
Body field Type Description
name string (max. 190)
description string (max. 2000)
duration_min integer (1–1440)
buffer_before integer (0–) Minutes kept free before, only against other appointments; not shown to clients.
buffer_after integer (0–)
price string or null For example "45" or "45.50"; shown only.
location_type string (in_person, client, phone, online)
location_details string (max. 255)
confirmation string (auto, review) auto confirms online bookings at once; review keeps them pending until the team confirms.
bookable_online boolean
min_notice_min integer or null
max_advance_days integer or null
sort_order integer
staff array of integer WordPress user ids of the staff members who do it (see kwazi/list-staff).
archived boolean

Answers: 200: id, name, description, duration_min, buffer_before, buffer_after, price, location_type, location_details, confirmation, bookable_online, min_notice_min, max_advance_days, form_id, sort_order, staff, archived, created_at, updated_at. Errors: error shape.

DELETE /services/{id} — Archive a service

Archives a service: it can no longer be booked, its appointments and history stay. Undo with kwazi/update-service and archived: false.

Permission: kwazi_manage_crm · Ability: kwazi/archive-service

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200: id, name, description, duration_min, buffer_before, buffer_after, price, location_type, location_details, confirmation, bookable_online, min_notice_min, max_advance_days, form_id, sort_order, staff, archived, created_at, updated_at. Errors: error shape.

Booking: team

GET /closures — List closures

Lists the days or hours the whole business is closed (holidays, closing days).

Permission: kwazi_view_contacts · Ability: kwazi/list-closures

Answers: 200. Errors: error shape.

POST /closures — Close the business for a day or a period

Adds time off (type closed) or extra hours (type extra, needs start and end) for a staff member, for one day or a period, all day or between two times. Without user_id it closes the whole business (managers only).

Permission: kwazi_manage_bookings · Ability: kwazi/add-time-off

Answers: 201. Errors: error shape.

DELETE /exceptions/{id} — Remove time off

Removes time off, extra hours or a closure of the business. Only use this when the user explicitly asks.

Permission: kwazi_manage_bookings · Ability: kwazi/remove-time-off

Parameter In Type Required Description
id path string (uuid) yes

Answers: 204. Errors: error shape.

GET /staff — List staff

Lists the staff members the user may see, with their weekly hours, the services they do and their meeting link for online appointments.

Permission: kwazi_view_contacts · Ability: kwazi/list-staff

Answers: 200. Errors: error shape.

POST /staff — Invite a staff member

Adds someone to the team by name, email address and role (staff by default; kwazi_admin; site_admin only by a website admin). A new address becomes a WordPress user with that role, who gets an email to choose a password; an existing user gets the role added (other roles stay; needs the right to promote that user). Confirm with the user first.

Permission: kwazi_manage_crm · Ability: kwazi/invite-staff

Body field Type Description
name string (max. 100)
email string (max. 190)
role string (site_admin, kwazi_admin, staff) Default staff. A Kwazi admin gives staff or kwazi_admin; only a website admin gives site_admin.

Answers: 200: user_id, created · 201: user_id, created. Errors: error shape.

GET /staff/invitations — List team invitations

Lists the invitations to the team that wait until the person accepts them: name, email address, role and until when the link works.

Permission: kwazi_manage_crm · Ability: kwazi/list-invitations

Answers: 200. Errors: error shape.

DELETE /staff/invitations/{id} — Revoke a team invitation

Withdraws an invitation that waits; its link stops working.

Permission: kwazi_manage_crm · Ability: kwazi/revoke-invitation

Parameter In Type Required Description
id path string yes

Answers: 204. Errors: error shape.

PATCH /staff/{user} — Update a staff member

Sets the name clients see (1 to 100 characters), the fixed meeting link of a staff member (http or https; empty clears it) and/or replaces the services they do (service ids; managers only). Staff members may change their own name and link.

Permission: kwazi_manage_bookings · Ability: kwazi/update-staff

Parameter In Type Required Description
user path integer yes
Body field Type Description
name string (max. 100)
meeting_url string (max. 2048)
services array of string (uuid)

Answers: 200: user_id, name, hours, services, meeting_url, role, sees, invited, name_is_login, access, roles_you_can_give, can_remove, can_rename. Errors: error shape.

DELETE /staff/{user} — Remove a team member

Removes someone from the team. The successor (another team member) takes over their contacts, organizations and appointments; refused when one of those appointments falls on one of the successor’s. The account is deleted when it has nothing else on the website, else it only loses its Kwazi role. Cannot be undone; confirm with the user first.

Permission: kwazi_manage_crm · Ability: kwazi/remove-staff

Parameter In Type Required Description
user path integer yes

Answers: 200: deleted, access_left. Errors: error shape.

GET /staff/{user}/exceptions — Time off and extra hours of a staff member

Returns the weekly hours of a staff member and their time off and extra hours.

Permission: kwazi_view_contacts · Ability: kwazi/get-staff-schedule

Parameter In Type Required Description
user path integer yes

Answers: 200. Errors: error shape.

POST /staff/{user}/exceptions — Add time off or extra hours

Adds time off (type closed) or extra hours (type extra, needs start and end) for a staff member, for one day or a period, all day or between two times. Without user_id it closes the whole business (managers only).

Permission: kwazi_manage_bookings · Ability: kwazi/add-time-off

Parameter In Type Required Description
user path integer yes
Body field Type Description
date_from string
date_to string
start string or null
end string or null
type string (closed, extra)
label string (max. 190)

Answers: 201: id, user_id, date_from, date_to, start, end, type, label, appointments. Errors: error shape.

GET /staff/{user}/hours — Weekly hours of a staff member

Returns the weekly hours of a staff member and their time off and extra hours.

Permission: kwazi_view_contacts · Ability: kwazi/get-staff-schedule

Parameter In Type Required Description
user path integer yes

Answers: 200. Errors: error shape.

PUT /staff/{user}/hours — Set working hours

Replaces the weekly working hours of a staff member. Weekdays left out have no hours. Staff members may set their own; managers anyone’s.

Permission: kwazi_manage_bookings · Ability: kwazi/update-staff-hours

Parameter In Type Required Description
user path integer yes
Body field Type Description
hours object Per ISO weekday ("1" = Monday … "7" = Sunday) a list of ["09:00", "12:00"] blocks, local time of the business.

Answers: 200: 1, 2, 3, 4, 5, 6, 7. Errors: error shape.

PUT /staff/{user}/role — Set the role of a team member

Gives a team member one of three roles: site_admin (everything on the website and in Kwazi), kwazi_admin (everything in Kwazi, nothing else on the website) or staff (the rights of Settings → Roles). A Kwazi admin never gives or changes site_admin; nobody lowers their own role or removes the last website admin.

Permission: kwazi_manage_crm · Ability: kwazi/set-staff-role

Parameter In Type Required Description
user path integer yes
Body field Type Description
role string (site_admin, kwazi_admin, staff)

Answers: 200: user_id, name, hours, services, meeting_url, role, sees, invited, name_is_login, access, roles_you_can_give, can_remove, can_rename. Errors: error shape.

GET /team — List the team

Lists the people who can own contacts (WordPress users with access to Kwazi), with their user id. Use the id as owner_user_id when assigning a contact.

Permission: kwazi_view_contacts · Ability: kwazi/list-team

Answers: 200. Errors: error shape.

Booking: website

GET /booking-widget/embed — Get the embed codes of the booking widget

Returns a shortcode and block markup for the booking widget (all services bookable online, or only one service and/or one staff member) the pages that already show a booking widget (used_on) and the booking page on its own (booking_page: its address, or null while it is off). Visitors cannot book online yet when used_on is empty and booking_page is null. Put it on a page with kwazi/embed-booking-in-page.

Permission: kwazi_view_contacts · Ability: kwazi/get-booking-embed

Parameter In Type Required Description
service query string (uuid) no
staff query integer (1–) no

Answers: 200: shortcode, block, used_on, booking_page. Errors: error shape.

POST /booking-widget/embed-in-page — Put the booking widget on a page

Adds the booking widget at the end of an existing page or post (page_id), or creates a new page with it (new_page_title). A new page is always a draft: tell the user to review and publish it (edit_url). Only works for pages the user may edit.

Permission: kwazi_manage_crm · Ability: kwazi/embed-booking-in-page

Body field Type Description
service string (uuid)
staff integer (1–) WordPress user id of a staff member (see kwazi/list-staff).
page_id integer (1–)
new_page_title string (max. 190)
publish boolean Publish a new page right away (needs publish_pages; otherwise a draft). Not available through the ability.

Answers: 200: page_id, status, edit_url, created. Errors: error shape.

Contacts

GET /contacts — Find contacts

Searches contacts (people) by name, email or phone, and filters by status, tag, owner, organization, source (see kwazi/list-contact-sources), last change, an appointment in a period, or no appointment since a moment (who has not been in since…). Returns at most limit contacts and a next_cursor for the next page. Only contacts the user may see are returned.

Permission: kwazi_view_contacts · Ability: kwazi/find-contacts

Parameter In Type Required Description
search query string (max. 100) no
status query string (lead, customer, inactive) no
marketing query string (none, pending, subscribed, unsubscribed) no
tag query string (max. 100) no
owner query integer (1–) no
organization query string (uuid) no
source query string (max. 50) no
appointment_from query string (date-time) no With an appointment (not cancelled or declined) starting at or after this moment.
appointment_to query string (date-time) no With an appointment starting before this moment.
no_appointment_since query string (date-time) no Without an appointment (not cancelled or declined) since this moment, also who never had one.
updated_since query string (date-time) no
created_since query string (date-time) no
include_deleted query boolean no
per_page query integer (1–100) no
cursor query string (max. 64) no

Answers: 200: items, next_cursor, total. Errors: error shape.

POST /contacts — Create a contact

Creates a contact. Needs at least a name, an email address or a phone number. Fails with kwazi_duplicate and the existing id when the email address is already used: update that contact instead.

Permission: kwazi_edit_contacts · Ability: kwazi/create-contact

Body field Type Description
first_name string (max. 100)
last_name string (max. 100)
email string (max. 190)
phone string (max. 50)
status string (lead, customer, inactive)
source string (max. 50)
owner_user_id integer or null (1–)
tags array of string (max. 100)
fields object Custom field values by field key; see kwazi/list-fields.

Answers: 201: id, first_name, last_name, email, phone, status, marketing, marketing_updated_at, source, owner_user_id, tags, fields, organization, last_activity, created_at, updated_at, deleted_at. Errors: error shape.

POST /contacts/duplicates — Find duplicate contacts

Checks whether a contact with this email address already exists, before creating one. Only the email address makes two contacts the same; names and phone numbers may repeat. A match the user may not see is reported without an id.

Permission: kwazi_view_contacts · Ability: kwazi/find-duplicates

Body field Type Description
email string (max. 190)

Answers: 200. Errors: error shape.

GET /contacts/sources — List contact sources

Lists where contacts came from (the source of each contact, e.g. a form, a fair or an import), alphabetically. Use one to filter kwazi/find-contacts.

Permission: kwazi_view_contacts · Ability: kwazi/list-contact-sources

Answers: 200. Errors: error shape.

GET /contacts/{id} — Get a contact

Returns one contact with its custom fields, tags, the organizations it belongs to and its most recent timeline entries (notes, changes, bookings). Use the id from kwazi/find-contacts.

Permission: kwazi_view_contacts · Ability: kwazi/get-contact

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200: id, first_name, last_name, email, phone, status, marketing, marketing_updated_at, source, owner_user_id, tags, fields, organization, last_activity, created_at, updated_at, deleted_at. Errors: error shape.

PATCH /contacts/{id} — Update a contact (fills empty values; ?mode=overwrite overwrites)

Enriches or corrects a contact. By default (mode fill_empty) only empty values are filled and tags are added; existing values are never overwritten. Use mode overwrite only when the user asks to replace values. Every change is logged with old and new values.

Permission: kwazi_edit_contacts · Ability: kwazi/update-contact

Parameter In Type Required Description
id path string (uuid) yes
Body field Type Description
mode string (fill_empty, overwrite)

Answers: 200. Errors: error shape.

DELETE /contacts/{id} — Delete a contact

Moves a contact to the trash. It can be restored with kwazi/restore-contact until the trash is emptied. Only use this when the user explicitly asks to delete.

Permission: kwazi_delete_contacts · Ability: kwazi/delete-contact

Parameter In Type Required Description
id path string (uuid) yes

Answers: 204. Errors: error shape.

GET /contacts/{id}/activities — Get the timeline of a contact

Returns timeline entries of a contact, newest first: notes, changes (with old and new values, channel and actor), links with organizations. Use next_cursor to page back in time.

Permission: kwazi_view_contacts · Ability: kwazi/get-contact-timeline

Parameter In Type Required Description
id path string (uuid) yes
per_page query integer (1–100) no
cursor query string (max. 64) no

Answers: 200: items, next_cursor, total. Errors: error shape.

GET /contacts/{id}/consents — Get the consents of a contact

Returns what a contact agreed to, oldest first: purpose (e.g. privacy, newsletter), the text exactly as the person saw it, when, and whether it was verified (confirmed by email). Consent from a public form is not verified.

Permission: kwazi_view_contacts · Ability: kwazi/get-contact-consents

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200. Errors: error shape.

POST /contacts/{id}/marketing/request — Ask a contact for marketing consent

Mails the contact a confirmation link; only after the person clicks it is the contact subscribed to marketing (double opt-in). Needs an email address; one mail per day at most. For an unsubscribed contact, a reason is required (e.g. "asked by phone on 14/10"). Never tell the user someone is subscribed before they confirmed.

Permission: kwazi_edit_contacts · Ability: kwazi/request-marketing-consent

Parameter In Type Required Description
id path string (uuid) yes
Body field Type Description
reason string (max. 255)

Answers: 200: id, first_name, last_name, email, phone, status, marketing, marketing_updated_at, source, owner_user_id, tags, fields, organization, last_activity, created_at, updated_at, deleted_at. Errors: error shape.

POST /contacts/{id}/marketing/unsubscribe — Unsubscribe a contact from marketing

Unsubscribes the contact from all marketing, at once. The address is remembered (as a hash), also if the contact is deleted later, so it is never subscribed again without the person confirming by email.

Permission: kwazi_edit_contacts · Ability: kwazi/unsubscribe-contact

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200: id, first_name, last_name, email, phone, status, marketing, marketing_updated_at, source, owner_user_id, tags, fields, organization, last_activity, created_at, updated_at, deleted_at. Errors: error shape.

POST /contacts/{id}/merge — Merge two contacts

Merges contact other_id into contact id when they are the same person. id wins: only its empty values are filled from other_id. Tags, organizations, timeline, consents, submissions and appointments move to id; values of other_id that differ are kept in the "merged" timeline entry. other_id is deleted for good. Only use this when the user explicitly asks to merge.

Permission: kwazi_delete_contacts · Ability: kwazi/merge-contacts

Parameter In Type Required Description
id path string (uuid) yes
Body field Type Description
other_id string (uuid)

Answers: 200: id, first_name, last_name, email, phone, status, marketing, marketing_updated_at, source, owner_user_id, tags, fields, organization, last_activity, created_at, updated_at, deleted_at. Errors: error shape.

POST /contacts/{id}/notes — Add a note to a contact

Adds a plain-text note to the timeline of a contact, e.g. a call summary or a follow-up reminder.

Permission: kwazi_edit_contacts · Ability: kwazi/add-note

Parameter In Type Required Description
id path string (uuid) yes
Body field Type Description
body string (max. 65535)

Answers: 201: type, subject, body, data, channel, actor_label, user_id, contact, created_at. Errors: error shape.

GET /contacts/{id}/organizations — Organizations a contact belongs to, with the role

Returns one contact with its custom fields, tags, the organizations it belongs to and its most recent timeline entries (notes, changes, bookings). Use the id from kwazi/find-contacts.

Permission: kwazi_view_contacts · Ability: kwazi/get-contact

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200. Errors: error shape.

POST /contacts/{id}/restore — Restore a contact

Takes a contact out of the trash, with its fields, tags, links and timeline.

Permission: kwazi_delete_contacts · Ability: kwazi/restore-contact

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200: id, first_name, last_name, email, phone, status, marketing, marketing_updated_at, source, owner_user_id, tags, fields, organization, last_activity, created_at, updated_at, deleted_at. Errors: error shape.

Custom fields

GET /field-groups — Groups of custom fields

Lists the custom fields of contacts or organizations (key, label, type, choices) and their groups. Use the keys in the fields object of create and update abilities.

Permission: kwazi_view_contacts · Ability: kwazi/list-fields

Parameter In Type Required Description
entity query string (contact, organization, submission) yes

Answers: 200. Errors: error shape.

POST /field-groups — Create a field group

Adds a group, e.g. "Billing", to show related custom fields together on screens.

Permission: kwazi_manage_crm · Ability: kwazi/create-field-group

Body field Type Description
entity string (contact, organization, submission)
label string (max. 190)

Answers: 201: id, entity, label, sort_order. Errors: error shape.

PATCH /field-groups/{id} — Update a field group

Renames a field group or changes its position among the other groups.

Permission: kwazi_manage_crm · Ability: kwazi/update-field-group

Parameter In Type Required Description
id path string (uuid) yes
Body field Type Description
label string (max. 190)
sort_order integer (0–)

Answers: 200: id, entity, label, sort_order. Errors: error shape.

DELETE /field-groups/{id} — Delete a field group

Deletes a field group. Its fields stay and simply lose their group. Only use this when the user explicitly asks to delete.

Permission: kwazi_manage_crm · Ability: kwazi/delete-field-group

Parameter In Type Required Description
id path string (uuid) yes

Answers: 204. Errors: error shape.

GET /fields — Custom fields of contacts or organizations

Lists the custom fields of contacts or organizations (key, label, type, choices) and their groups. Use the keys in the fields object of create and update abilities.

Permission: kwazi_view_contacts · Ability: kwazi/list-fields

Parameter In Type Required Description
entity query string (contact, organization, submission) yes
include_archived query boolean no

Answers: 200. Errors: error shape.

POST /fields — Create a custom field

Adds a custom field to contacts or organizations. The key is derived from the label and never changes. Types: text, long_text, email, phone, url, number, date, dropdown, choices, checkbox. Dropdown and choices need options.

Permission: kwazi_manage_crm · Ability: kwazi/create-field

Body field Type Description
entity string (contact, organization, submission)
type string (text, long_text, email, phone, url, number, date, dropdown, choices, checkbox)
label string (max. 190)
options array of string (max. 190) Choices, for dropdown and choices fields.
group string or null (uuid)
show_in_list boolean

Answers: 201: id, entity, key, label, type, options, group, sort_order, source, show_in_list, archived, created_at. Errors: error shape.

PATCH /fields/{id} — Update a custom field

Changes the label, choices, group, order or list visibility of a custom field, or archives it (archived: true). Archiving hides the field but keeps its values; archived: false brings it back. Key and type never change.

Permission: kwazi_manage_crm · Ability: kwazi/update-field

Parameter In Type Required Description
id path string (uuid) yes
Body field Type Description
label string (max. 190)
options array of string (max. 190) Choices, for dropdown and choices fields.
group string or null (uuid)
show_in_list boolean
sort_order integer (0–)
archived boolean

Answers: 200: id, entity, key, label, type, options, group, sort_order, source, show_in_list, archived, created_at. Errors: error shape.

DELETE /fields/{id} — Archive a custom field (its values are kept)

Changes the label, choices, group, order or list visibility of a custom field, or archives it (archived: true). Archiving hides the field but keeps its values; archived: false brings it back. Key and type never change.

Permission: kwazi_manage_crm · Ability: kwazi/update-field

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200. Errors: error shape.

Exports

GET /exports/audit-log.csv — Export the audit log

Exports the audit log as CSV text (UTF-8, header row first), optionally for one channel or action. The export itself is recorded in the audit log.

Permission: kwazi_manage_integrations · Ability: kwazi/export-audit-log

Parameter In Type Required Description
channel query string (app, portal, api, ability, form, booking, import, email, system) no
action query string (max. 60) no

Answers: 200 (CSV). Errors: error shape.

GET /exports/contacts.csv — Export contacts

Exports the contacts matching the filters as CSV text (UTF-8, header row first), with the same filters as kwazi/find-contacts. Only contacts the user may see are included.

Permission: kwazi_export_contacts · Ability: kwazi/export-contacts

Parameter In Type Required Description
search query string (max. 100) no
status query string (lead, customer, inactive) no
marketing query string (none, pending, subscribed, unsubscribed) no
tag query string (max. 100) no
owner query integer (1–) no
organization query string (uuid) no
source query string (max. 50) no
appointment_from query string (date-time) no With an appointment (not cancelled or declined) starting at or after this moment.
appointment_to query string (date-time) no With an appointment starting before this moment.
no_appointment_since query string (date-time) no Without an appointment (not cancelled or declined) since this moment, also who never had one.
created_since query string (date-time) no
ids query array of string (uuid) no
separator query string (,, 😉 no

Answers: 200 (CSV). Errors: error shape.

GET /exports/organizations.csv — Export organizations

Exports the organizations matching the filters as CSV text (UTF-8, header row first): name, VAT number, contact details, address, owner, number of linked contacts and custom fields.

Permission: kwazi_export_contacts · Ability: kwazi/export-organizations

Parameter In Type Required Description
search query string (max. 100) no
owner query integer (1–) no
separator query string (,, 😉 no

Answers: 200 (CSV). Errors: error shape.

GET /exports/submissions.csv — Export form submissions

Exports the form submissions the user may see as CSV, one column per submitted value, filtered by form and status.

Permission: kwazi_manage_forms · Ability: kwazi/export-submissions

Parameter In Type Required Description
form query integer (1–) no
status query string (received, spam) no
separator query string (,, 😉 no

Answers: 200 (CSV). Errors: error shape.

Forms

GET /forms — List forms

Lists every form with its status (publish or draft), its definition, the pages that show it and the number of submissions received and blocked as spam in the last 30 days.

Permission: kwazi_view_contacts · Ability: kwazi/list-forms

Answers: 200. Errors: error shape.

POST /forms — Create a form

Creates a form, as a draft unless status is publish. Give a definition, or a template key from kwazi/list-form-templates (fields the template needs are created). Each field element needs a target from the field library (e.g. contact.first_name, contact.email, submission.fields.message; see kwazi/list-fields). A consent element with marketing: true asks the visitor to confirm by email before they are subscribed. Put it on a page with kwazi/embed-in-page. Leave notify.emails empty: the user adds notification addresses in the app.

Permission: kwazi_manage_forms · Ability: kwazi/create-form

Body field Type Description
name string (max. 190)
status string (draft, publish)
definition object elements (field, heading, paragraph, consent), submit_label, after_submit, notify, new_contacts. A field element links to a target such as contact.email or contact.fields.<key>; a consent element with marketing: true asks for confirmation by email.
template string (max. 50)

Answers: 201: id, name, status, definition, submissions_30d, spam_30d, used_on, booking, created_at, updated_at. Errors: error shape.

GET /forms/templates — List form templates

Lists ready-made forms (contact, quote request, callback request, newsletter) with their definition. Create one with kwazi/create-form and the template key.

Permission: kwazi_manage_forms · Ability: kwazi/list-form-templates

Answers: 200. Errors: error shape.

GET /forms/{id} — Get a form

Returns one form with its full definition: elements (fields linked to contact, organization or submission fields, headings, paragraphs, consents), the button text, what happens after sending and who is notified.

Permission: kwazi_view_contacts · Ability: kwazi/get-form

Parameter In Type Required Description
id path integer yes

Answers: 200: id, name, status, definition, submissions_30d, spam_30d, used_on, booking, created_at, updated_at. Errors: error shape.

PATCH /forms/{id} — Update a form

Changes the name, the status (publish or draft) and/or the definition of a form. A definition replaces the whole previous one: send every element again. Notification addresses (notify.emails) can be kept or removed here, not added: the user adds those in the app.

Permission: kwazi_manage_forms · Ability: kwazi/update-form

Parameter In Type Required Description
id path integer yes
Body field Type Description
name string (max. 190)
status string (draft, publish)
definition object elements (field, heading, paragraph, consent), submit_label, after_submit, notify, new_contacts. A field element links to a target such as contact.email or contact.fields.<key>; a consent element with marketing: true asks for confirmation by email.

Answers: 200: id, name, status, definition, submissions_30d, spam_30d, used_on, booking, created_at, updated_at. Errors: error shape.

DELETE /forms/{id} — Delete a form

Moves a form to the trash; its submissions stay. Pages that show it will no longer show a form. Only use this when the user explicitly asks to delete.

Permission: kwazi_manage_forms · Ability: kwazi/delete-form

Parameter In Type Required Description
id path integer yes

Answers: 204. Errors: error shape.

POST /forms/{id}/duplicate — Duplicate a form

Makes a draft copy of a form, with " (copy)" after the name.

Permission: kwazi_manage_forms · Ability: kwazi/duplicate-form

Parameter In Type Required Description
id path integer yes

Answers: 201: id, name, status, definition, submissions_30d, spam_30d, used_on, booking, created_at, updated_at. Errors: error shape.

GET /forms/{id}/embed — Get the embed codes of a form

Returns a shortcode (works in any editor) and block markup (block editor) to show a form on a page.

Permission: kwazi_view_contacts · Ability: kwazi/get-embed

Parameter In Type Required Description
id path integer yes

Answers: 200: shortcode, block. Errors: error shape.

POST /forms/{id}/embed-in-page — Put a form on a page

Adds the form at the end of an existing page or post (page_id), or creates a new page with it (new_page_title). A new page is always a draft: tell the user to review and publish it (edit_url). Only works for pages the user may edit.

Permission: kwazi_manage_forms · Ability: kwazi/embed-in-page

Parameter In Type Required Description
id path integer yes
Body field Type Description
page_id integer (1–)
new_page_title string (max. 190)

Answers: 200: page_id, status, edit_url, created · 201: page_id, status, edit_url, created. Errors: error shape.

POST /forms/{id}/submit — Submit a published form as a website visitor (honeypot, time token, rate limit).

Public: no login (website visitors).

Parameter In Type Required Description
id path integer yes

Answers: 200. Errors: error shape.

GET /forms/{id}/token — A fresh time token for a published form (pages served from a cache).

Public: no login (website visitors).

Parameter In Type Required Description
id path integer yes

Answers: 200. Errors: error shape.

Imports

POST /imports — Upload a CSV import

Uploads CSV text (max. 5 MB, header row first) to import contacts. Nothing is imported yet: the result shows the columns, a guessed mapping and a preview. Check the mapping with the user, then call kwazi/start-import.

Permission: kwazi_import_contacts · Ability: kwazi/create-import

Body field Type Description
file_name string (max. 190)
csv string (max. 5242880)

Answers: 201: id, file_name, status, headers, mapping, options, preview, totals, errors, created_at, finished_at. Errors: error shape.

GET /imports/{id} — Get an import

Returns the status, totals and first errors of a CSV import.

Permission: kwazi_import_contacts · Ability: kwazi/get-import

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200: id, file_name, status, headers, mapping, options, preview, totals, errors, created_at, finished_at. Errors: error shape.

PATCH /imports/{id} — Correct the column mapping and options of an import

Imports the rows of an uploaded CSV, optionally with a corrected mapping and options. duplicates: fill_empty (default; only fills empty values of an existing contact with the same email address), skip or overwrite. tag is added to every imported contact. Large files continue in the background; check with kwazi/get-import.

Permission: kwazi_import_contacts · Ability: kwazi/start-import

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200. Errors: error shape.

GET /imports/{id}/errors.csv — The rows of an import that failed, with the reason

Returns the status, totals and first errors of a CSV import.

Permission: kwazi_import_contacts · Ability: kwazi/get-import

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200 (CSV). Errors: error shape.

POST /imports/{id}/start — Start an import

Imports the rows of an uploaded CSV, optionally with a corrected mapping and options. duplicates: fill_empty (default; only fills empty values of an existing contact with the same email address), skip or overwrite. tag is added to every imported contact. Large files continue in the background; check with kwazi/get-import.

Permission: kwazi_import_contacts · Ability: kwazi/start-import

Parameter In Type Required Description
id path string (uuid) yes
Body field Type Description
mapping array of string Target per column, in column order: first_name, last_name, email, phone, status, source, tags, fields.<key>, or "" to skip the column.
options object

Answers: 200: id, file_name, status, headers, mapping, options, preview, totals, errors, created_at, finished_at. Errors: error shape.

Marketing (public)

POST /marketing/confirm — Confirm a marketing subscription with the token from the email (double opt-in).

Public: no login (website visitors).

Body field Type Description
token string (max. 200)

Answers: 200. Errors: error shape.

POST /marketing/unsubscribe — Unsubscribe from marketing with the token from an email.

Public: no login (website visitors).

Body field Type Description
token string (max. 200)

Answers: 200. Errors: error shape.

Organizations

GET /organizations — Find organizations

Searches organizations (companies, associations…) by name, VAT number, email or city. Returns at most limit organizations and a next_cursor for the next page.

Permission: kwazi_view_contacts · Ability: kwazi/find-organizations

Parameter In Type Required Description
search query string (max. 100) no
updated_since query string (date-time) no
owner query integer (1–) no
per_page query integer (1–100) no
cursor query string (max. 64) no

Answers: 200: items, next_cursor, total. Errors: error shape.

POST /organizations — Create an organization

Creates an organization. Needs a name. VAT numbers are stored without spaces or dots; a website without https:// gets it added.

Permission: kwazi_edit_contacts · Ability: kwazi/create-organization

Body field Type Description
name string (max. 190)
vat_number string (max. 30)
email string (max. 190)
phone string (max. 50)
website string (max. 2048)
address_line string (max. 255)
postal_code string (max. 20)
city string (max. 100)
country string (max. 2) ISO 3166-1 alpha-2 code, e.g. BE.
owner_user_id integer or null (1–)
fields object Custom field values by field key; see kwazi/list-fields.

Answers: 201: id, name, vat_number, email, phone, website, address_line, postal_code, city, country, owner_user_id, fields, contacts_count, last_activity, created_at, updated_at, deleted_at. Errors: error shape.

POST /organizations/duplicates — Find similar organizations

Before creating an organization: lists existing ones with the same name (ignoring legal forms such as BV, NV, SRL or GmbH, case and punctuation), the same VAT number or the same email address, each with its reasons. Creating a similar one is still allowed, e.g. for a second branch.

Permission: kwazi_view_contacts · Ability: kwazi/find-organization-duplicates

Body field Type Description
name string (max. 190)
vat_number string (max. 30)
email string (max. 190)

Answers: 200. Errors: error shape.

GET /organizations/possible-duplicates — List possible duplicate organizations

Lists pairs of organizations that may be the same (same name without legal form, VAT number or email address), oldest first, at most 100. Pairs marked with kwazi/dismiss-organization-duplicate are left out. Merge a real duplicate with kwazi/merge-organizations.

Permission: kwazi_view_contacts · Ability: kwazi/list-organization-duplicates

Answers: 200. Errors: error shape.

GET /organizations/{id} — Get an organization

Returns one organization with its custom fields and the people linked to it (with their role). Only people the user may see are listed.

Permission: kwazi_view_contacts · Ability: kwazi/get-organization

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200: id, name, vat_number, email, phone, website, address_line, postal_code, city, country, owner_user_id, fields, contacts_count, last_activity, created_at, updated_at, deleted_at. Errors: error shape.

PATCH /organizations/{id} — Update an organization (fills empty values; ?mode=overwrite overwrites)

Enriches or corrects an organization. By default (mode fill_empty) only empty values are filled; existing values are never overwritten. Use mode overwrite only when the user asks to replace values.

Permission: kwazi_edit_contacts · Ability: kwazi/update-organization

Parameter In Type Required Description
id path string (uuid) yes
Body field Type Description
mode string (fill_empty, overwrite)

Answers: 200. Errors: error shape.

DELETE /organizations/{id} — Delete an organization

Moves an organization to the trash. Its people stay. It can be restored with kwazi/restore-organization. Only use this when the user explicitly asks to delete.

Permission: kwazi_delete_contacts · Ability: kwazi/delete-organization

Parameter In Type Required Description
id path string (uuid) yes

Answers: 204. Errors: error shape.

GET /organizations/{id}/activities — Get the timeline of an organization

Returns the timeline of an organization and of the people linked to it, newest first. Each entry about a person names that person. Use next_cursor to page back in time.

Permission: kwazi_view_contacts · Ability: kwazi/get-organization-timeline

Parameter In Type Required Description
id path string (uuid) yes
per_page query integer (1–100) no
cursor query string (max. 64) no

Answers: 200: items, next_cursor, total. Errors: error shape.

GET /organizations/{id}/contacts — People linked to an organization, with their role

Returns one organization with its custom fields and the people linked to it (with their role). Only people the user may see are listed.

Permission: kwazi_view_contacts · Ability: kwazi/get-organization

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200. Errors: error shape.

Links a person to an organization with an optional role (e.g. Owner, Accountant), or changes the role of an existing link. is_primary marks the main organization of that person.

Permission: kwazi_edit_contacts · Ability: kwazi/link-contact-organization

Parameter In Type Required Description
id path string (uuid) yes
contact_id path string (uuid) yes

Answers: 204. Errors: error shape.

Removes the link between a person and an organization. Both stay; the timeline keeps a record of the link.

Permission: kwazi_edit_contacts · Ability: kwazi/unlink-contact-organization

Parameter In Type Required Description
id path string (uuid) yes
contact_id path string (uuid) yes

Answers: 204. Errors: error shape.

POST /organizations/{id}/merge — Merge two organizations

Merges organization other_id into organization id when they are the same. id wins: only its empty values are filled from other_id. People, timeline and submissions move to id; values of other_id that differ are kept in the "merged" timeline entry. other_id is deleted for good. Only use this when the user explicitly asks to merge.

Permission: kwazi_delete_contacts · Ability: kwazi/merge-organizations

Parameter In Type Required Description
id path string (uuid) yes
Body field Type Description
other_id string (uuid)

Answers: 200: id, name, vat_number, email, phone, website, address_line, postal_code, city, country, owner_user_id, fields, contacts_count, last_activity, created_at, updated_at, deleted_at. Errors: error shape.

POST /organizations/{id}/not-duplicate — Mark organizations as different

Marks two organizations as not the same (e.g. two branches with one VAT number), so the pair no longer appears in kwazi/list-organization-duplicates.

Permission: kwazi_edit_contacts · Ability: kwazi/dismiss-organization-duplicate

Parameter In Type Required Description
id path string (uuid) yes
Body field Type Description
other_id string (uuid)

Answers: 204. Errors: error shape.

POST /organizations/{id}/restore — Restore an organization

Takes an organization out of the trash, with its links to people and its custom fields.

Permission: kwazi_delete_contacts · Ability: kwazi/restore-organization

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200: id, name, vat_number, email, phone, website, address_line, postal_code, city, country, owner_user_id, fields, contacts_count, last_activity, created_at, updated_at, deleted_at. Errors: error shape.

Overview

GET /overview — Get the overview

Returns what is going on: today’s appointments (how many are still to come), the requests waiting for confirmation (soonest 5 and the total), new contacts and form submissions of the last 7 days, and the 10 newest timeline entries with their contact. Only what the user may see. Use it to answer "what is on today?" or "anything new?".

Permission: kwazi_view_contacts · Ability: kwazi/get-overview

Answers: 200: today, requests, new_contacts, submissions, activity. Errors: error shape.

Privacy

POST /privacy/erase — Erase personal data

Permanently erases the person with this email address and everything linked to them (GDPR erasure request). This cannot be undone and skips the trash. Only use this when the user explicitly asks to erase someone’s data.

Permission: kwazi_manage_crm · Ability: kwazi/erase-personal-data

Body field Type Description
email string (email; max. 190)

Answers: 200: erased. Errors: error shape.

POST /privacy/personal-data — Export personal data

Returns everything Kwazi holds about the person with this email address (GDPR access request): contact details, custom fields, tags, organizations, timeline and consents, also from the trash. Returns null when there is nobody with that address.

Permission: kwazi_manage_crm · Ability: kwazi/export-personal-data

Body field Type Description
email string (email; max. 190)

Answers: 200. Errors: error shape.

Settings

GET /settings/api-access — Get who may use application passwords

Returns the roles that may reach Kwazi with an application password (they skip two-factor login), and the roles to choose from. Other plugins are not affected.

Permission: kwazi_manage_integrations · Ability: kwazi/get-api-access

Answers: 200: roles, available. Errors: error shape.

PATCH /settings/api-access — Change who may use application passwords

Sets the roles that may reach Kwazi with an application password. A change of rights: hidden from MCP by default.

Permission: kwazi_manage_integrations · Ability: kwazi/update-api-access

Body field Type Description
roles array of string

Answers: 200: roles, available. Errors: error shape.

GET /settings/booking — Get the booking settings

Returns the booking settings: grid of start times, notice and horizon for visitors, how long before the start a visitor may still cancel, reminders, terms and the default form for the details step. The business details are in kwazi/get-general-settings.

Permission: kwazi_view_contacts · Ability: kwazi/get-booking-settings

Answers: 200: slot_step, min_notice_min, max_advance_days, cancel_notice_hours, late_cancel_text, reminder_enabled, reminder_hours, terms_text, default_confirmation, client_changes, max_open_bookings, form_id. Errors: error shape.

PATCH /settings/booking — Update the booking settings

Changes the booking settings that are given; anything left out stays. A service can set its own notice, horizon and form instead. Business details are changed with kwazi/update-general-settings.

Permission: kwazi_manage_crm · Ability: kwazi/update-booking-settings

Body field Type Description
slot_step integer (0–240) Minutes between start times (0 = the length of the service; otherwise at least 5).
min_notice_min integer (0–43200) Default earliest start for visitors, in minutes from now.
max_advance_days integer (1–730) Default latest start for visitors, in days from now.
cancel_notice_hours integer (0–720) Visitors may cancel or move until this many hours before the start.
late_cancel_text string (max. 1000) Shown to a visitor when it is too late to cancel or move (empty = a standard text).
reminder_enabled boolean Send one reminder email before each confirmed appointment.
reminder_hours integer (1–168) How many hours before the start the reminder goes out.
terms_text string (max. 1000) Plain text above the book button, e.g. a cancellation fee (empty = none).
default_confirmation string (auto, review) Confirmation mode of a new service that sets none: auto (confirmed at once) or review (the team confirms each request).
client_changes boolean Visitors may cancel and move online with the link in their mail (until cancel_notice_hours before the start).
max_open_bookings integer (0–50) Upcoming appointments (requested or confirmed) one contact can book online; 0 = no maximum. The team can always book more.
form_id integer Default form for the details step (see kwazi/list-forms); it must have a required email field.

Answers: 200: slot_step, min_notice_min, max_advance_days, cancel_notice_hours, late_cancel_text, reminder_enabled, reminder_hours, terms_text, default_confirmation, client_changes, max_open_bookings, form_id. Errors: error shape.

GET /settings/form-style — Get the style of forms

Returns the site style of forms and the booking widget: font, sizes, weights, colours (hex), radius and the submit button (icon, width). A property that is missing follows the theme. A form can override any property in its definition (style).

Permission: kwazi_view_contacts · Ability: kwazi/get-form-style

Answers: 200: font, size, color, label_size, label_weight, label_style, label_transform, label_color, heading_size, heading_weight, heading_color, field_background, field_border, field_text, field_radius, focus_color, button_background, button_text, button_radius, button_weight, button_transform, button_decoration, button_width, button_icon, button_icon_position, error_color, background, container. Errors: error shape.

PATCH /settings/form-style — Change the style of forms

Changes the site style of forms and the booking widget; only the properties sent change, "" or null puts one back to the theme. Colours are hex (#rrggbb), sizes whole pixels. Mind the contrast between text and background.

Permission: kwazi_manage_crm · Ability: kwazi/update-form-style

Body field Type Description
font string or null theme, system-sans, system-serif, system-mono, kwazi:inter, kwazi:lora, kwazi:merriweather, kwazi:montserrat, kwazi:nunito, or theme:<slug> for a font of the theme.
size integer or string or null (12–24)
color string or null
label_size integer or string or null (12–24)
label_weight integer or string or null (400, 500, 600, 700, )
label_style string or string or null (normal, italic, )
label_transform string or string or null (none, uppercase, )
label_color string or null
heading_size integer or string or null (16–40)
heading_weight integer or string or null (400, 500, 600, 700, )
heading_color string or null
field_background string or null
field_border string or null
field_text string or null
field_radius integer or string or null (0–24)
focus_color string or null
button_background string or null
button_text string or null
button_radius integer or string or null (0–40)
button_weight integer or string or null (400, 500, 600, 700, )
button_transform string or string or null (none, uppercase, )
button_decoration string or string or null (none, underline, )
button_width string or string or null (auto, full, )
button_icon string or string or null (arrow-right, chevron-right, send, check, check-circle, calendar, clock, mail, phone, message, user, users, download, heart, star, sparkles, gift, ticket, lock, plus, )
button_icon_position string or string or null (left, right, )
error_color string or null
background string or null
container string or string or null (card, plain, )

Answers: 200: font, size, color, label_size, label_weight, label_style, label_transform, label_color, heading_size, heading_weight, heading_color, field_background, field_border, field_text, field_radius, focus_color, button_background, button_text, button_radius, button_weight, button_transform, button_decoration, button_width, button_icon, button_icon_position, error_color, background, container. Errors: error shape.

GET /settings/general — Get the general settings

Returns the business details (name, email for clients, phone, VAT number, address), the currency of prices, the trusted proxy header, and the time zone and first day of the week of WordPress.

Permission: kwazi_manage_crm · Ability: kwazi/get-general-settings

Answers: 200: business, reply_to, currency, country, countries, ip_header, ip_headers, ip_headers_seen, timezone, week_start. Errors: error shape.

PATCH /settings/general — Change the general settings

Changes the business details, the currency, the country for phone numbers and/or the trusted proxy header that are given. The email for clients cannot be changed this way. The proxy header decides the rate limits of public forms: hidden from MCP by default.

Permission: kwazi_manage_crm · Ability: kwazi/update-general-settings

Body field Type Description
business object
currency string Currency of prices (ISO 4217), e.g. EUR.
country string (BE, NL, FR, DE, AT, CH, GB, ) Country of the business (ISO 3166-1 alpha-2): imported and submitted phone numbers starting with 0 get its calling code. Empty keeps numbers as typed.
ip_header string Proxy header with the visitor’s address (e.g. HTTP_CF_CONNECTING_IP), or empty for the direct connection. Only choose one of a proxy the site is surely behind: anyone can send these headers.

Answers: 200: business, reply_to, currency, country, countries, ip_header, ip_headers, ip_headers_seen, timezone, week_start. Errors: error shape.

GET /settings/portal — Get portal settings

Returns the staff portal settings: its path and address, whether staff stay out of wp-admin, required two-factor login, sign-out after inactivity, logo and "Powered by Kwazi", plus the active 2FA plugin and login protection.

Permission: kwazi_manage_crm · Ability: kwazi/get-portal-settings

Answers: 200: path, staff_out, require_2fa, idle_hours, logo_id, powered_by, booking_page, host, url, pretty_urls, path_status, logo_url, two_factor, login_protection, site_admin, booking_url, host_reachable, host_https, host_checked_at, host_active. Errors: error shape.

PATCH /settings/portal — Change portal settings

Changes the portal settings that are given. Security settings (two-factor login, wp-admin access, sign-out): hidden from MCP by default.

Permission: kwazi_manage_crm · Ability: kwazi/update-portal-settings

Body field Type Description
path string (max. 50) Path of the portal on the site, e.g. kwazi for /kwazi/: lower-case letters, digits and hyphens. A path a page, post or other route uses cannot be chosen.
staff_out boolean Users with only the Kwazi staff role are sent from wp-admin to the portal.
require_2fa boolean Everyone with a Kwazi role needs active two-factor login (from a 2FA plugin) for the app, the portal and the API through a browser login.
idle_hours integer (1, 8, 24) Sign a Kwazi user out after this many hours without a request.
logo_id integer or null Image from the media library for the portal, its login screen and the booking page; null = the business name.
powered_by boolean Show a small "Powered by Kwazi" on the booking widget and page, the portal login and client emails. Off unless turned on.
booking_page boolean The booking widget on its own page without the theme, at the portal path + /book (or /book on the portal host). Off unless turned on.
host string (max. 253) Own (sub)domain of the portal, e.g. team.example.com; "" for none. The portal moves there once kwazi/check-portal-host passed.

Answers: 200: path, staff_out, require_2fa, idle_hours, logo_id, powered_by, booking_page, host, url, pretty_urls, path_status, logo_url, two_factor, login_protection, site_admin, booking_url, host_reachable, host_https, host_checked_at, host_active. Errors: error shape.

POST /settings/portal/check-host — Check the portal host

Checks that the portal host (its own subdomain) reaches this site and has valid HTTPS. When both pass, the portal moves to that host; until then it stays on its path.

Permission: kwazi_manage_crm · Ability: kwazi/check-portal-host

Answers: 200: path, staff_out, require_2fa, idle_hours, logo_id, powered_by, booking_page, host, url, pretty_urls, path_status, logo_url, two_factor, login_protection, site_admin, booking_url, host_reachable, host_https, host_checked_at, host_active. Errors: error shape.

GET /settings/portal/path — Check a portal path

Whether a path can be the address of the staff portal: null when free, otherwise invalid, reserved (a WordPress path) or in_use (a page, post or other route).

Permission: kwazi_manage_crm · Ability: kwazi/check-portal-path

Parameter In Type Required Description
path query string (max. 100) yes

Answers: 200: path, status, url. Errors: error shape.

GET /settings/privacy — Get the privacy settings

Returns how long Kwazi keeps spam, the webhook log, the audit log and deleted contacts (in days), and whether deleting the plugin deletes all Kwazi data too.

Permission: kwazi_manage_crm · Ability: kwazi/get-privacy-settings

Answers: 200: delete_on_uninstall, retention. Errors: error shape.

PATCH /settings/privacy — Change the privacy settings

Sets whether deleting the plugin deletes all Kwazi data and tables too. Hidden from MCP by default: it decides about all data.

Permission: kwazi_manage_crm · Ability: kwazi/update-privacy-settings

Body field Type Description
delete_on_uninstall boolean

Answers: 200: delete_on_uninstall, retention. Errors: error shape.

GET /settings/roles — Get roles and visibility

Returns what each role may do in Kwazi (its Kwazi capabilities) and which records it sees (all, or only its own contacts and appointments), plus the roles that can be added. The administrator is fixed. Needs the right to give users roles.

Permission: kwazi_manage_crm · Ability: kwazi/get-roles

Answers: 200: roles, available. Errors: error shape.

PATCH /settings/roles/{role} — Change a role

Sets the Kwazi capabilities of a role (all of them; an empty list takes the role out of Kwazi) and/or which records it sees. Every capability needs kwazi_view_contacts; you can only give rights you have. A change of rights: hidden from MCP by default.

Permission: kwazi_manage_crm · Ability: kwazi/update-role

Parameter In Type Required Description
role path string yes
Body field Type Description
capabilities array of string (kwazi_manage_crm, kwazi_view_contacts, kwazi_edit_contacts, kwazi_delete_contacts, kwazi_import_contacts, kwazi_export_contacts, kwazi_manage_bookings, kwazi_manage_forms, kwazi_manage_integrations)
visibility string (all, own) all: every contact and appointment; own: contacts the user owns and appointments with them.

Answers: 200: roles, available. Errors: error shape.

GET /settings/telemetry — Get what is shared with Kwazi

Whether anonymous usage statistics and the company profile are shared with Kwazi (both off unless the site owner turned them on in the app), and exactly what the statistics would send. Consent can only be given or taken by a person in the app.

Permission: kwazi_manage_crm · Ability: kwazi/get-telemetry

Answers: 200: stats, profile, profile_data, last_sent, live, payload. Errors: error shape.

Body field Type Description
stats boolean Share anonymous usage statistics once a week.
profile boolean Share the company profile for product news (a confirmation email comes first).
profile_data object company, website, name, email, sector, team_size.

Answers: 200. Errors: error shape.

Submissions

GET /submissions — Find form submissions

Lists form submissions, newest first, filtered by form and status (received or spam). Only submissions of contacts the user may see are returned. Returns at most limit items and a next_cursor.

Permission: kwazi_view_contacts · Ability: kwazi/find-submissions

Parameter In Type Required Description
form query integer (1–) no
status query string (received, spam) no
contact query string (uuid) no
per_page query integer (1–100) no
cursor query string (max. 64) no
created_since query string (date-time) no Only submissions received at or after this moment (ISO 8601). Submissions do not change after they are sent, so poll on this.

Answers: 200: items, next_cursor, total. Errors: error shape.

GET /submissions/{id} — Get a form submission

Returns one form submission: the values as sent, the linked contact and organization, the page it came from and, for spam, why it was blocked.

Permission: kwazi_view_contacts · Ability: kwazi/get-submission

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200: id, form, status, result, contact, organization, values, page, spam_reason, error, created_at. Errors: error shape.

DELETE /submissions/{id} — Delete a form submission

Permanently deletes a form submission. The contact it created stays. Only use this when the user explicitly asks to delete.

Permission: kwazi_manage_forms · Ability: kwazi/delete-submission

Parameter In Type Required Description
id path string (uuid) yes

Answers: 204. Errors: error shape.

POST /submissions/{id}/not-spam — Mark a submission as not spam

Takes a submission out of spam and processes it as if it came in normally: the contact is created or filled in.

Permission: kwazi_manage_forms · Ability: kwazi/mark-submission-not-spam

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200: id, form, status, result, contact, organization, values, page, spam_reason, error, created_at. Errors: error shape.

Tags

GET /tags — List tags

Lists every tag with its slug. Use a slug to filter kwazi/find-contacts, or a name to tag a contact.

Permission: kwazi_view_contacts · Ability: kwazi/list-tags

Answers: 200. Errors: error shape.

POST /tags — Create a tag (or get the existing one with the same slug)

Creates a tag, or returns the existing tag with the same slug. Tags are also created automatically when you tag a contact.

Permission: kwazi_edit_contacts · Ability: kwazi/create-tag

Answers: 200: name, slug · 201: name, slug. Errors: error shape.

This document

GET /openapi.json — This document: the OpenAPI 3.1 description of this installation

Answers: 200. Errors: error shape.

Webhooks

GET /webhook-deliveries/{id} — Get a webhook delivery

Returns one delivery: the body as sent, its status, attempts, last HTTP status and error, and when it is tried again.

Permission: kwazi_manage_integrations · Ability: kwazi/get-webhook-delivery

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200: id, event, event_id, status, attempts, response_code, error, duration_ms, next_attempt_at, created_at, delivered_at, payload. Errors: error shape.

POST /webhook-deliveries/{id}/resend — Resend a webhook delivery

Tries a delivery again right away, with a fresh signature, and returns the result.

Permission: kwazi_manage_integrations · Ability: kwazi/resend-webhook-delivery

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200: id, event, event_id, status, attempts, response_code, error, duration_ms, next_attempt_at, created_at, delivered_at, payload. Errors: error shape.

GET /webhooks — List webhooks

Lists every webhook with its address, events, whether it is on, and why it paused (20 failures in a row, or an unreadable secret). Secrets are never returned.

Permission: kwazi_manage_integrations · Ability: kwazi/list-webhooks

Answers: 200. Errors: error shape.

POST /webhooks — Create a webhook

Subscribes an https address to public events. Returns the signing secret once. Hidden from MCP by default: only run it when the site owner asks for this exact address.

Permission: kwazi_manage_integrations · Ability: kwazi/create-webhook

Body field Type Description
name string (max. 190)
url string (max. 500) https address on port 443 of a public host.
events array of string (contact.created, contact.updated, contact.deleted, contact.restored, contact.merged, contact.erased, organization.created, organization.updated, organization.deleted, organization.restored, organization.merged, marketing.subscribed, marketing.unsubscribed, form.submitted, appointment.booked, appointment.confirmed, appointment.declined, appointment.rescheduled, appointment.place_changed, appointment.cancelled, appointment.completed, appointment.no_show)
active boolean

Answers: 201: webhook, secret. Errors: error shape.

GET /webhooks/events — List webhook events

Lists the public events a webhook can subscribe to on this site, such as contact.created or appointment.booked. Events of apps that are switched off are not listed.

Permission: kwazi_manage_integrations · Ability: kwazi/list-webhook-events

Answers: 200. Errors: error shape.

GET /webhooks/{id} — Get a webhook

Returns one webhook: address, events, on or off, pause reason and the last 4 characters of its secret.

Permission: kwazi_manage_integrations · Ability: kwazi/get-webhook

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200: id, name, url, events, active, paused, failures, secret_hint, created_at, updated_at. Errors: error shape.

PATCH /webhooks/{id} — Update a webhook

Changes the name, address, events or on/off of a webhook. Switching a webhook paused for failures on again resumes it. Hidden from MCP by default.

Permission: kwazi_manage_integrations · Ability: kwazi/update-webhook

Parameter In Type Required Description
id path string (uuid) yes
Body field Type Description
name string (max. 190)
url string (max. 500) https address on port 443 of a public host.
events array of string (contact.created, contact.updated, contact.deleted, contact.restored, contact.merged, contact.erased, organization.created, organization.updated, organization.deleted, organization.restored, organization.merged, marketing.subscribed, marketing.unsubscribed, form.submitted, appointment.booked, appointment.confirmed, appointment.declined, appointment.rescheduled, appointment.place_changed, appointment.cancelled, appointment.completed, appointment.no_show)
active boolean

Answers: 200: id, name, url, events, active, paused, failures, secret_hint, created_at, updated_at. Errors: error shape.

DELETE /webhooks/{id} — Delete a webhook

Deletes a webhook and its delivery log. Only use this when the user explicitly asks to delete.

Permission: kwazi_manage_integrations · Ability: kwazi/delete-webhook

Parameter In Type Required Description
id path string (uuid) yes

Answers: 204. Errors: error shape.

GET /webhooks/{id}/deliveries — Find webhook deliveries

Lists the deliveries of a webhook (kept 30 days), newest first, optionally by status: queued, retrying, delivered or failed. Returns at most limit items and a next_cursor.

Permission: kwazi_manage_integrations · Ability: kwazi/find-webhook-deliveries

Parameter In Type Required Description
id path string (uuid) yes
status query string (queued, retrying, delivered, failed) no
cursor query string (max. 64) no
per_page query integer (1–100) no

Answers: 200: items, next_cursor, total. Errors: error shape.

POST /webhooks/{id}/secret — Make a new webhook secret

Replaces the signing secret of a webhook; the old one stops working at once. Returns the new secret once. Hidden from MCP by default.

Permission: kwazi_manage_integrations · Ability: kwazi/regenerate-webhook-secret

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200: webhook, secret. Errors: error shape.

POST /webhooks/{id}/test — Send a test event to a webhook

Sends a signed webhook.test event right away and returns the delivery with the HTTP status of the receiver.

Permission: kwazi_manage_integrations · Ability: kwazi/test-webhook

Parameter In Type Required Description
id path string (uuid) yes

Answers: 200: id, event, event_id, status, attempts, response_code, error, duration_ms, next_attempt_at, created_at, delivered_at, payload. Errors: error shape.

apps

GET /apps — List apps

Lists the Kwazi apps (Contacts, Forms, Booking and installed add-ons) and whether each is on. The abilities of an app that is off do not exist.

Permission: kwazi_view_contacts · Ability: kwazi/list-apps

Answers: 200. Errors: error shape.

PATCH /apps/{app} — Turn an app on or off

Turns an app on or off for the whole site. Off: its screens, routes, abilities, website parts and reminders are gone; its data stays and comes back when it is turned on. Contacts is always on. A change for the whole site: hidden from MCP by default.

Permission: kwazi_manage_crm · Ability: kwazi/update-app

Parameter In Type Required Description
app path string yes
Body field Type Description
enabled boolean

Answers: 200. Errors: error shape.

feedback

POST /feedback/deactivate — Send why the plugin is deactivated (the plugins screen asks; only the reason, the text and the versions go to Kwazi)

Body field Type Description
reason string temporary, missing_feature, too_hard, not_working, other_tool or other.
text string (max. 1000)

Answers: 200. Errors: error shape.

integrations

GET /integrations/ai — Get the status for AI assistants

Whether the Abilities API and the MCP Adapter are there (with its server address), which roles may connect with an application password, what connecting with one prompt needs for the reader (site, login, whether application passwords are available and allowed with Kwazi), and every Kwazi ability with whether an assistant may use it (mcp) and whether it only reads.

Permission: kwazi_manage_integrations · Ability: kwazi/get-ai-status

Answers: 200: abilities_api, adapter, connect_roles, abilities, connect. Errors: error shape.

setup

GET /setup — Get the state of the setup guide

Whether the setup guide (opening hours, a first service, a booking page and the choices about sharing) is done or skipped.

Permission: kwazi_manage_crm · Ability: kwazi/get-setup

Answers: 200: done, dismissed. Errors: error shape.

PATCH /setup — Mark the setup guide done or skipped

Marks the setup guide done and/or skipped, so it no longer opens by itself. The steps themselves are the abilities for hours, services and the booking page.

Permission: kwazi_manage_crm · Ability: kwazi/update-setup

Body field Type Description
done boolean
dismissed boolean

Answers: 200: done, dismissed. Errors: error shape.

support

GET /support — Get the support status

Whether Kwazi support can be reached from the app, and exactly what technical info a support request carries when the person ticks it. Sending a request can only be done by a person in the app.

Permission: kwazi_view_contacts · Ability: kwazi/get-support

Answers: 200: live, environment. Errors: error shape.

POST /support/requests — Send a question, bug or idea to Kwazi support (only from the app: a person sends it, not an integration or AI assistant)

Body field Type Description
type string question, bug, idea.
subject string One line, at most 150 characters.
message string At most 5000 characters.
reply_to string Where Kwazi replies.
include_environment boolean Send the technical info of GET /support along.

Answers: 200. Errors: error shape.

Still stuck?

A real person answers, in plain words. Use the help form, or ask on the WordPress forum.

Ask us a question