{"openapi":"3.1.0","info":{"title":"Adaab API","version":"1"},"servers":[{"url":"https://arm.adab.solutions/api/v1"}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer"}}},"security":[{"bearer":[]}],"paths":{"/contacts":{"get":{"operationId":"contacts_search","summary":"Search contacts by name, email or phone (q), status, tag or list. Newest first.","tags":["contacts"],"description":"Use this to find people before acting on them: look someone up by part of their name, email or phone, or pull everyone with a status, tag or on a list. Results are newest first and paged with limit and offset. To walk the whole database, keep adding limit to offset until fewer than limit come back.\n\nReturns { data: [contact, …] }. Each contact has its id, names, email, phone, status, source, campaign, tags, custom fields and opt-outs.","x-permission":"contacts:read","parameters":[{"name":"q","in":"query","required":false,"schema":{"description":"Words to look for in the name, email or phone. Partial matches count: \"amin\" finds Amina.","type":"string","maxLength":200}},{"name":"status","in":"query","required":false,"schema":{"description":"Only people with exactly this status, e.g. donor or lead.","type":"string"}},{"name":"tag","in":"query","required":false,"schema":{"description":"Only people with this tag.","type":"string"}},{"name":"list_id","in":"query","required":false,"schema":{"description":"Only people on this list (see lists_list for ids).","type":"string","pattern":"^[A-Za-z0-9]{12}$"}},{"name":"limit","in":"query","required":false,"schema":{"default":50,"description":"How many to return, 1 to 200.","type":"integer","minimum":1,"maximum":200}},{"name":"offset","in":"query","required":false,"schema":{"default":0,"description":"How many to skip, for the next page.","type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"{ data: [contact, …] }. Each contact has its id, names, email, phone, status, source, campaign, tags, custom fields and opt-outs.","content":{"application/json":{"example":{"data":[{"id":"k3Jd9QmZp2Lx","first_name":"Amina","last_name":"Khan","email":"amina@example.org","phone":"+447700900123","status":"donor","source":"website","campaign":"Ramadan 2026","tags":["monthly","volunteer"],"fields":{"city":"Leeds"},"email_opt_out":false,"whatsapp_opt_out":false,"created_at":"2026-09-14T10:22:05.000Z","updated_at":"2026-10-01T08:00:00.000Z"}]}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"}}},"post":{"operationId":"contacts_create","summary":"Create a contact, or update the existing one with the same email or phone (upsert). Fires automations and webhooks.","tags":["contacts"],"description":"Adds a person, or updates them if someone with the same email or phone is already there, so it is safe to call from a sign-up form every time. Only the fields you send are set. New people start any \"new contact\" automations and send the contact.created webhook; updates send contact.updated.\n\nReturns { created, contact }. created is true for a new person, false when an existing one was updated.","x-permission":"contacts:write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"first_name":{"description":"Their first name.","type":"string","maxLength":100},"last_name":{"description":"Their last name.","type":"string","maxLength":100},"email":{"description":"Their email address. Used to find an existing person.","anyOf":[{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"type":"null"}]},"phone":{"description":"Their phone number, best with the country code (+44…). Used to find an existing person.","anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"status":{"description":"Where they are with you, e.g. lead, donor, volunteer.","type":"string","maxLength":80},"source":{"description":"Where they came from, e.g. website or event.","type":"string","maxLength":200},"campaign":{"description":"The campaign that brought them in.","type":"string","maxLength":200},"tags":{"description":"Labels to add. Up to 50.","maxItems":50,"type":"array","items":{"type":"string","maxLength":80}},"fields":{"description":"Custom columns by key, e.g. {\"city\": \"Leeds\"}. See Columns in the app for the keys.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"email_opt_out":{"description":"true if they asked not to be emailed.","type":"boolean"},"whatsapp_opt_out":{"description":"true if they asked not to get WhatsApp messages.","type":"boolean"},"sms_opt_out":{"description":"true if they asked not to get text messages.","type":"boolean"}},"required":[]},"example":{"first_name":"Amina","last_name":"Khan","email":"amina@example.org","source":"website","tags":["newsletter"]}}}},"responses":{"201":{"description":"{ created, contact }. created is true for a new person, false when an existing one was updated.","content":{"application/json":{"example":{"created":true,"contact":{"id":"k3Jd9QmZp2Lx","first_name":"Amina","last_name":"Khan","email":"amina@example.org","phone":"+447700900123","status":"donor","source":"website","campaign":"Ramadan 2026","tags":["monthly","volunteer"],"fields":{"city":"Leeds"},"email_opt_out":false,"whatsapp_opt_out":false,"created_at":"2026-09-14T10:22:05.000Z","updated_at":"2026-10-01T08:00:00.000Z"}}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"}}}},"/contacts/{id}":{"get":{"operationId":"contacts_get","summary":"One contact with their notes, open tasks, lists and giving summary.","tags":["contacts"],"description":"Everything about one person in one call: their details, the last 20 notes, the lists they are on and a giving summary per currency. Use it before writing to someone or when an assistant needs context about a supporter.\n\nReturns The contact, plus notes (newest first), lists ({ id, name }) and giving ({ currency, gifts, total, last_gift }).","x-permission":"contacts:read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9]{12}$","description":"The contact's id, 12 letters and digits."}}],"responses":{"200":{"description":"The contact, plus notes (newest first), lists ({ id, name }) and giving ({ currency, gifts, total, last_gift }).","content":{"application/json":{"example":{"id":"k3Jd9QmZp2Lx","first_name":"Amina","last_name":"Khan","email":"amina@example.org","phone":"+447700900123","status":"donor","source":"website","campaign":"Ramadan 2026","tags":["monthly","volunteer"],"fields":{"city":"Leeds"},"email_opt_out":false,"whatsapp_opt_out":false,"created_at":"2026-09-14T10:22:05.000Z","updated_at":"2026-10-01T08:00:00.000Z","notes":[{"id":"Nte1Aa2Bb3Cc","body":"Prefers WhatsApp.","created_at":"2026-09-20T12:00:00.000Z"}],"lists":[{"id":"Lst7Hq2Wn4Ra","name":"Monthly givers"}],"giving":[{"currency":"GBP","gifts":7,"total":350,"last_gift":"2026-09-30"}]}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"},"404":{"description":"No contact with that id in this organisation. Search for them with contacts_search."}}},"patch":{"operationId":"contacts_update","summary":"Change a contact. Only the fields given change; custom fields are merged.","tags":["contacts"],"description":"Changes some of a person's details. Fields you leave out stay as they are, and custom fields are merged, so sending {\"fields\": {\"city\": \"York\"}} keeps their other custom fields.\n\nReturns The contact as it is now.","x-permission":"contacts:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9]{12}$","description":"The contact's id."}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"first_name":{"type":"string","maxLength":100},"last_name":{"type":"string","maxLength":100},"email":{"anyOf":[{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"type":"null"}]},"phone":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"status":{"type":"string","maxLength":80},"source":{"type":"string","maxLength":200},"campaign":{"type":"string","maxLength":200},"tags":{"maxItems":50,"type":"array","items":{"type":"string","maxLength":80}},"fields":{"description":"Custom columns by key, e.g. {\"city\": \"Leeds\"}","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"email_opt_out":{"type":"boolean"},"whatsapp_opt_out":{"type":"boolean"},"sms_opt_out":{"type":"boolean"}},"required":[]},"example":{"status":"donor","fields":{"city":"York"}}}}},"responses":{"200":{"description":"The contact as it is now.","content":{"application/json":{"example":{"id":"k3Jd9QmZp2Lx","first_name":"Amina","last_name":"Khan","email":"amina@example.org","phone":"+447700900123","status":"donor","source":"website","campaign":"Ramadan 2026","tags":["monthly","volunteer"],"fields":{"city":"York"},"email_opt_out":false,"whatsapp_opt_out":false,"created_at":"2026-09-14T10:22:05.000Z","updated_at":"2026-10-01T08:00:00.000Z"}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"},"404":{"description":"No contact with that id in this organisation."}}}},"/contacts/{id}/notes":{"post":{"operationId":"notes_add","summary":"Add a note to a contact.","tags":["contacts"],"description":"Writes a note on someone's record, as the person who made the API key. Good for logging a conversation, a phone call or what an assistant found out.\n\nReturns The note: { id, body, created_at }.","x-permission":"contacts:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9]{12}$","description":"The contact's id."}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string","minLength":1,"maxLength":5000,"description":"The note, up to 5,000 characters."}},"required":["body"]},"example":{"body":"Called to say thank you. Happy to hear about the winter appeal."}}}},"responses":{"201":{"description":"The note: { id, body, created_at }.","content":{"application/json":{"example":{"id":"Nte9Zz8Yy7Xx","body":"Called to say thank you. Happy to hear about the winter appeal.","created_at":"2026-10-04T09:30:00.000Z"}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"},"404":{"description":"No contact with that id."}}}},"/lists":{"get":{"operationId":"lists_list","summary":"Every list, with how many people are on it.","tags":["lists"],"description":"Every list in the organisation with how many people are on it. Use the ids with contacts_search, lists_add_contacts and letters_queue.\n\nReturns { data: [{ id, name, description, members }, …] }, by name.","x-permission":"lists:read","parameters":[],"responses":{"200":{"description":"{ data: [{ id, name, description, members }, …] }, by name.","content":{"application/json":{"example":{"data":[{"id":"Lst7Hq2Wn4Ra","name":"Monthly givers","description":"Anyone with an active standing order","members":214}]}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"}}}},"/lists/{id}/members":{"post":{"operationId":"lists_add_contacts","summary":"Add contacts to a list (fires \"joined list\" automations).","tags":["lists"],"description":"Puts people on a list. People already on it are left alone and not counted. Each newly added person starts the list's \"joined list\" automations.\n\nReturns { added }: how many were newly added.","x-permission":"lists:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9]{12}$","description":"The list's id."}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contact_ids":{"minItems":1,"maxItems":500,"type":"array","items":{"type":"string","pattern":"^[A-Za-z0-9]{12}$"},"description":"The people to add, 1 to 500 ids."}},"required":["contact_ids"]},"example":{"contact_ids":["k3Jd9QmZp2Lx"]}}}},"responses":{"201":{"description":"{ added }: how many were newly added.","content":{"application/json":{"example":{"added":1}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"},"404":{"description":"No list with that id in this organisation."}}}},"/tasks":{"get":{"operationId":"tasks_list","summary":"Tasks that are not done yet (or done ones), optionally for one contact.","tags":["tasks"],"description":"Things the team has to do. By default only open tasks, soonest due first; send done=true for finished ones.\n\nReturns { data: [{ id, title, due_on, contact_id, assignee_id, done_at, created_at }, …] }.","x-permission":"tasks:read","parameters":[{"name":"contact_id","in":"query","required":false,"schema":{"description":"Only tasks about this person.","type":"string","pattern":"^[A-Za-z0-9]{12}$"}},{"name":"done","in":"query","required":false,"schema":{"default":false,"description":"true for finished tasks, false (the default) for open ones.","type":"boolean"}},{"name":"limit","in":"query","required":false,"schema":{"default":50,"type":"integer","minimum":1,"maximum":200}},{"name":"offset","in":"query","required":false,"schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"{ data: [{ id, title, due_on, contact_id, assignee_id, done_at, created_at }, …] }.","content":{"application/json":{"example":{"data":[{"id":"Tsk5Bv8Cx1Ny","title":"Call Amina about Gift Aid","due_on":"2026-10-07","contact_id":"k3Jd9QmZp2Lx","assignee_id":"Usr4Ee5Rr6Tt","done_at":null,"created_at":"2026-10-01T09:00:00.000Z"}]}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"}}},"post":{"operationId":"tasks_create","summary":"Create a task, optionally about a contact and for a member (defaults to the key's owner).","tags":["tasks"],"description":"Adds a task, optionally about a person and for a team member. Without assignee_id it goes to whoever made the API key.\n\nReturns { id, title, due_on }.","x-permission":"tasks:write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200,"description":"What needs doing, up to 200 characters."},"due_on":{"description":"The day it is due, like 2026-10-07.","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"},"contact_id":{"description":"The person it is about.","type":"string","pattern":"^[A-Za-z0-9]{12}$"},"assignee_id":{"description":"The team member who should do it.","type":"string","pattern":"^[A-Za-z0-9]{12}$"}},"required":["title"]},"example":{"title":"Call Amina about Gift Aid","due_on":"2026-10-07","contact_id":"k3Jd9QmZp2Lx"}}}},"responses":{"201":{"description":"{ id, title, due_on }.","content":{"application/json":{"example":{"id":"Tsk5Bv8Cx1Ny","title":"Call Amina about Gift Aid","due_on":"2026-10-07"}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"},"404":{"description":"The contact was not found."}}}},"/tasks/{id}/done":{"post":{"operationId":"tasks_complete","summary":"Mark a task done.","tags":["tasks"],"description":"Ticks a task off. Doing it twice is harmless: the first finish time is kept.\n\nReturns { id, done_at }.","x-permission":"tasks:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9]{12}$","description":"The task's id."}}],"responses":{"201":{"description":"{ id, done_at }.","content":{"application/json":{"example":{"id":"Tsk5Bv8Cx1Ny","done_at":"2026-10-04T11:15:00.000Z"}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"},"404":{"description":"No task with that id."}}}},"/donations":{"get":{"operationId":"donations_list","summary":"Donations, newest first, filtered by contact, fund or date range.","tags":["donations"],"description":"Gifts received, newest first. Refunded gifts are included with refunded_on set, so you can match your own records exactly.\n\nReturns { data: [{ id, contact_id, amount, currency, received_on, fund, method, reference, gift_aid, claim_id, pledge_id, refunded_on, created_at }, …] }.","x-permission":"donations:read","parameters":[{"name":"contact_id","in":"query","required":false,"schema":{"description":"Only this person's gifts.","type":"string","pattern":"^[A-Za-z0-9]{12}$"}},{"name":"fund","in":"query","required":false,"schema":{"description":"Only gifts to this fund, e.g. General or Zakat.","type":"string"}},{"name":"from","in":"query","required":false,"schema":{"description":"Received on or after this day.","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"to","in":"query","required":false,"schema":{"description":"Received on or before this day.","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"limit","in":"query","required":false,"schema":{"default":50,"type":"integer","minimum":1,"maximum":200}},{"name":"offset","in":"query","required":false,"schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"{ data: [{ id, contact_id, amount, currency, received_on, fund, method, reference, gift_aid, claim_id, pledge_id, refunded_on, created_at }, …] }.","content":{"application/json":{"example":{"data":[{"id":"Don2Rt6Yp9Ke","contact_id":"k3Jd9QmZp2Lx","amount":"50.00","currency":"GBP","received_on":"2026-09-30","fund":"General","method":"card","reference":"WEB-1042","gift_aid":true,"claim_id":null,"pledge_id":null,"refunded_on":null,"created_at":"2026-09-30T18:02:11.000Z"}]}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"}}},"post":{"operationId":"donations_record","summary":"Record a donation for a contact. Give external_id (your system's id) so a retry never records it twice. Fires thank-you automations.","tags":["donations"],"description":"Records a gift from a person. Send external_id with your own system's id for the gift: if the same external_id comes again (a retry, a re-sync) nothing is recorded twice. Recording a gift starts thank-you automations and sends the donation.created webhook. Tick gift_aid only when they have a valid declaration.\n\nReturns { recorded: true, donation } or, when the external_id was seen before, { recorded: false, reason }.","x-permission":"donations:write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contact_id":{"type":"string","pattern":"^[A-Za-z0-9]{12}$","description":"Who gave."},"amount":{"type":"number","exclusiveMinimum":0,"maximum":10000000,"multipleOf":0.01,"description":"How much, e.g. 25 or 25.50."},"currency":{"default":"GBP","description":"Three-letter currency, GBP by default.","type":"string","pattern":"^[A-Z]{3}$"},"received_on":{"description":"The day it arrived; today if left out.","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"},"fund":{"default":"General","description":"Which fund it goes to. General by default.","type":"string","maxLength":80},"method":{"default":"","description":"How it was paid, e.g. card, cash, bank transfer.","type":"string","maxLength":60},"reference":{"default":"","description":"Your reference for it, shown on their record.","type":"string","maxLength":120},"gift_aid":{"default":false,"description":"true if Gift Aid can be claimed on it.","type":"boolean"},"pledge_id":{"description":"A pledge of theirs this pays towards.","type":"string","pattern":"^[A-Za-z0-9]{12}$"},"external_id":{"description":"Your system's id for the gift, so it is never recorded twice.","type":"string","maxLength":200}},"required":["contact_id","amount"]},"example":{"contact_id":"k3Jd9QmZp2Lx","amount":25,"fund":"Winter appeal","method":"card","gift_aid":true,"external_id":"stripe_pi_3Px"}}}},"responses":{"201":{"description":"{ recorded: true, donation } or, when the external_id was seen before, { recorded: false, reason }.","content":{"application/json":{"example":{"recorded":true,"donation":{"id":"Don2Rt6Yp9Ke","amount":"25.00","currency":"GBP","received_on":"2026-10-04","fund":"Winter appeal"}}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"},"404":{"description":"The contact was not found."}}}},"/donations/{id}/refund":{"post":{"operationId":"donations_refund","summary":"Mark a donation refunded. It stays on record but stops counting and is never claimed for Gift Aid.","tags":["donations"],"description":"Marks a gift as refunded. It stays on their record for history but no longer counts in totals and is never claimed for Gift Aid. If it was already in a Gift Aid claim, the answer tells you which claim needs adjusting.\n\nReturns { refunded: true, gift_aid_claim_to_adjust }: the claim id, or null.","x-permission":"donations:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9]{12}$","description":"The donation's id."}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"default":"","description":"Why, for the record.","type":"string","maxLength":500},"refunded_on":{"description":"The day of the refund; today if left out.","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},"required":[]},"example":{"reason":"Paid twice by mistake"}}}},"responses":{"201":{"description":"{ refunded: true, gift_aid_claim_to_adjust }: the claim id, or null.","content":{"application/json":{"example":{"refunded":true,"gift_aid_claim_to_adjust":null}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"},"404":{"description":"No donation with that id."}}}},"/donations/summary":{"get":{"operationId":"donations_summary","summary":"Income by month and fund over a date range (default: the last 12 months).","tags":["donations"],"description":"Income totals by month, fund and currency, leaving out refunds. Handy for a dashboard or for an assistant answering \"how did the appeal do?\".\n\nReturns { data: [{ month, fund, currency, gifts, total }, …] } in month order.","x-permission":"donations:read","parameters":[{"name":"from","in":"query","required":false,"schema":{"description":"First day to count; 12 months ago if left out.","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"to","in":"query","required":false,"schema":{"description":"Last day to count; today if left out.","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}}],"responses":{"200":{"description":"{ data: [{ month, fund, currency, gifts, total }, …] } in month order.","content":{"application/json":{"example":{"data":[{"month":"2026-09","fund":"General","currency":"GBP","gifts":42,"total":3150.5}]}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"}}}},"/recurring-gifts":{"get":{"operationId":"recurring_gifts_list","summary":"Active recurring gifts (standing orders, Direct Debits, card subscriptions).","tags":["donations"],"description":"Regular gifts that are still running: standing orders, Direct Debits and card subscriptions.\n\nReturns { data: [{ id, contact_id, amount, currency, frequency, fund, method, gift_aid, started_on }, …] }.","x-permission":"donations:read","parameters":[{"name":"contact_id","in":"query","required":false,"schema":{"description":"Only this person's.","type":"string","pattern":"^[A-Za-z0-9]{12}$"}}],"responses":{"200":{"description":"{ data: [{ id, contact_id, amount, currency, frequency, fund, method, gift_aid, started_on }, …] }.","content":{"application/json":{"example":{"data":[{"id":"Rec3Qq4Ww5Ee","contact_id":"k3Jd9QmZp2Lx","amount":"10.00","currency":"GBP","frequency":"monthly","fund":"General","method":"direct_debit","gift_aid":true,"started_on":"2025-01-01"}]}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"}}}},"/pledges":{"get":{"operationId":"pledges_list","summary":"Pledges with how much has been paid and their status (open, overdue, fulfilled, cancelled).","tags":["pledges"],"description":"Promises to give, with how much has come in against each.\n\nReturns { data: [{ id, contact_id, amount, currency, fund, due_on, notes, cancelled_on, created_at, paid, status }, …] }: open and overdue first, up to 500.","x-permission":"donations:read","parameters":[{"name":"contact_id","in":"query","required":false,"schema":{"description":"Only this person's pledges.","type":"string","pattern":"^[A-Za-z0-9]{12}$"}},{"name":"status","in":"query","required":false,"schema":{"description":"open, overdue, fulfilled or cancelled.","type":"string","enum":["open","overdue","fulfilled","cancelled"]}}],"responses":{"200":{"description":"{ data: [{ id, contact_id, amount, currency, fund, due_on, notes, cancelled_on, created_at, paid, status }, …] }: open and overdue first, up to 500.","content":{"application/json":{"example":{"data":[{"id":"Plg4Mn7Qs2Vb","contact_id":"k3Jd9QmZp2Lx","amount":"500.00","currency":"GBP","fund":"Building","due_on":"2026-09-01","notes":"","cancelled_on":null,"created_at":"2026-06-01T10:00:00.000Z","paid":200,"status":"overdue"}]}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"}}},"post":{"operationId":"pledges_create","summary":"Record a promise to give. Donations recorded with its pledge_id count towards it.","tags":["pledges"],"description":"Records a promise to give. Gifts recorded later with this pledge_id count towards it, and it becomes fulfilled when they add up.\n\nReturns { id }: the new pledge's id. Send it as pledge_id when recording the gifts that pay it.","x-permission":"donations:write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contact_id":{"type":"string","pattern":"^[A-Za-z0-9]{12}$","description":"Who promised."},"amount":{"type":"number","exclusiveMinimum":0,"maximum":10000000,"multipleOf":0.01,"description":"How much they promised."},"currency":{"default":"GBP","description":"Three-letter currency, GBP by default.","type":"string","pattern":"^[A-Z]{3}$"},"fund":{"default":"General","description":"Which fund. General by default.","type":"string","maxLength":80},"due_on":{"description":"When it should be paid by.","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"},"notes":{"default":"","description":"Anything worth remembering.","type":"string","maxLength":2000}},"required":["contact_id","amount"]},"example":{"contact_id":"k3Jd9QmZp2Lx","amount":500,"fund":"Building","due_on":"2026-12-31"}}}},"responses":{"201":{"description":"{ id }: the new pledge's id. Send it as pledge_id when recording the gifts that pay it.","content":{"application/json":{"example":{"id":"Plg4Mn7Qs2Vb"}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"}}}},"/donors/rfm":{"get":{"operationId":"donors_rfm","summary":"Donors scored 1-5 on recency, frequency and money given, with a segment: Champions, Loyal, Big givers, New, At risk, Lapsed, Needs attention.","tags":["donations"],"description":"Scores every donor from 1 to 5 on how recently, how often and how much they give, and names a segment. Use it to choose who to thank, upgrade or win back.\n\nReturns { data: [{ contact_id, first_name, last_name, email, last_gift, gifts, total, r, f, m, segment }, …] }. r, f and m are the 1 to 5 scores; up to 500 donors.","x-permission":"donations:read","parameters":[{"name":"segment","in":"query","required":false,"schema":{"description":"Only donors in this segment.","type":"string","enum":["Champions","Loyal","Big givers","New","At risk","Lapsed","Needs attention"]}},{"name":"contact_id","in":"query","required":false,"schema":{"description":"Only this donor.","type":"string","pattern":"^[A-Za-z0-9]{12}$"}},{"name":"currency","in":"query","required":false,"schema":{"default":"GBP","description":"Which currency to score in, GBP by default.","type":"string","pattern":"^[A-Z]{3}$"}},{"name":"limit","in":"query","required":false,"schema":{"default":200,"description":"How many, 1 to 2,000.","type":"integer","minimum":1,"maximum":2000}}],"responses":{"200":{"description":"{ data: [{ contact_id, first_name, last_name, email, last_gift, gifts, total, r, f, m, segment }, …] }. r, f and m are the 1 to 5 scores; up to 500 donors.","content":{"application/json":{"example":{"data":[{"contact_id":"k3Jd9QmZp2Lx","first_name":"Amina","last_name":"Khan","email":"amina@example.org","last_gift":"2025-11-02","gifts":9,"total":640,"r":2,"f":4,"m":4,"segment":"At risk"}]}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"}}}},"/beneficiaries":{"get":{"operationId":"beneficiaries_list","summary":"Sponsorship beneficiaries and their current sponsor, if any.","tags":["sponsorships"],"description":"People or projects that can be sponsored, with their sponsor if they have one.\n\nReturns { data: [{ id, code, name, scheme, country, sponsor_id, amount, currency, started_on }, …] }.","x-permission":"sponsorships:read","parameters":[{"name":"scheme","in":"query","required":false,"schema":{"description":"Only this sponsorship scheme.","type":"string"}},{"name":"unsponsored","in":"query","required":false,"schema":{"default":false,"description":"true to see only those still waiting for a sponsor.","type":"boolean"}}],"responses":{"200":{"description":"{ data: [{ id, code, name, scheme, country, sponsor_id, amount, currency, started_on }, …] }.","content":{"application/json":{"example":{"data":[{"id":"Ben5Tt6Yy7Uu","code":"ORP-0142","name":"Yusuf","scheme":"Orphan care","country":"Kenya","sponsor_id":null,"amount":null,"currency":null,"started_on":null}]}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"}}}},"/call-campaigns":{"get":{"operationId":"call_campaigns_list","summary":"Calling campaigns with calls made, money raised and pledged against target.","tags":["calls"],"description":"Phone campaigns with progress: calls made, money raised and pledged, against the target.\n\nReturns { data: [{ id, name, list_id, target, active, created_at, calls, people, raised, pledged, outcomes }, …] }.","x-permission":"calls:make","parameters":[],"responses":{"200":{"description":"{ data: [{ id, name, list_id, target, active, created_at, calls, people, raised, pledged, outcomes }, …] }.","content":{"application/json":{"example":{"data":[{"id":"Cmp8Fz3Gh6Jw","name":"Winter thank-you calls","list_id":"Lst7Hq2Wn4Ra","target":5000,"active":true,"created_at":"2026-09-01T09:00:00.000Z","calls":38,"people":35,"raised":1240,"pledged":600,"outcomes":[{"outcome":"donated","n":12}]}]}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"}}}},"/call-campaigns/{id}/next":{"post":{"operationId":"calls_next","summary":"Take the next person to call in a campaign (or your call still open). Returns the call id and the contact.","tags":["calls"],"description":"Gives you the next person to ring in a campaign, and holds them for you so nobody else calls them at the same time. If you already have a call open, you get that one back.\n\nReturns { call_id, contact } or, when nobody is left, { call: null, message }.","x-permission":"calls:make","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9]{12}$","description":"The campaign's id."}}],"responses":{"201":{"description":"{ call_id, contact } or, when nobody is left, { call: null, message }.","content":{"application/json":{"example":{"call_id":"Cal1Xs5Dk8Tq","contact":{"id":"k3Jd9QmZp2Lx","first_name":"Amina","last_name":"Khan","phone":"+447700900123","email":"amina@example.org"}}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"}}}},"/calls/{id}":{"post":{"operationId":"calls_log","summary":"Close your open call with its outcome. donated records a donation, pledged a pledge, callback a task.","tags":["calls"],"description":"Closes your open call with what happened. donated also records the gift (send amount), pledged records a pledge, and callback makes a task for callback_on.\n\nReturns { logged: true }.","x-permission":"calls:make","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9]{12}$","description":"The call id from calls_next."}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"outcome":{"type":"string","enum":["answered","donated","pledged","callback","no_answer","voicemail","declined","wrong_number","do_not_call"],"description":"What happened on the call."},"notes":{"default":"","description":"Notes from the call.","type":"string","maxLength":5000},"amount":{"description":"For donated or pledged: how much.","type":"number","exclusiveMinimum":0,"maximum":10000000,"multipleOf":0.01},"fund":{"default":"General","description":"The fund for the gift or pledge.","type":"string","maxLength":80},"callback_on":{"description":"For callback: the day to ring again.","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},"required":["outcome"]},"example":{"outcome":"donated","amount":30,"notes":"Gave over the phone."}}}},"responses":{"201":{"description":"{ logged: true }.","content":{"application/json":{"example":{"logged":true}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"}}}},"/letters":{"post":{"operationId":"letters_queue","summary":"Queue a letter template for contacts (or everyone on a list) to be printed. Contacts missing a merge field are skipped.","tags":["letters"],"description":"Puts a letter template in the print queue for some people, or everyone on a list. People missing something the letter needs (like an address) are skipped and counted.\n\nReturns { queued, skipped, already }: letters queued, people skipped for missing details, and people who already had this letter waiting.","x-permission":"letters:write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"template_id":{"type":"string","pattern":"^[A-Za-z0-9]{12}$","description":"The letter template."},"contact_ids":{"default":[],"description":"The people to write to.","maxItems":5000,"type":"array","items":{"type":"string","pattern":"^[A-Za-z0-9]{12}$"}},"list_id":{"description":"Or everyone on this list.","type":"string","pattern":"^[A-Za-z0-9]{12}$"}},"required":["template_id"]},"example":{"template_id":"Tpl6Wq9Er3Zu","list_id":"Lst7Hq2Wn4Ra"}}}},"responses":{"201":{"description":"{ queued, skipped, already }: letters queued, people skipped for missing details, and people who already had this letter waiting.","content":{"application/json":{"example":{"queued":212,"skipped":2,"already":0}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"}}}},"/templates":{"get":{"operationId":"templates_list","summary":"Email and WhatsApp templates that can be sent.","tags":["templates"],"description":"The email and WhatsApp templates you can send with messages_send.\n\nReturns { data: [{ id, channel, name, subject, active }, …] }.","x-permission":"templates:read","parameters":[],"responses":{"200":{"description":"{ data: [{ id, channel, name, subject, active }, …] }.","content":{"application/json":{"example":{"data":[{"id":"Tpl6Wq9Er3Zu","channel":"email","name":"Thank you for your gift","subject":"Thank you, {{first_name}}","active":true}]}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"}}}},"/messages":{"post":{"operationId":"messages_send","summary":"Send an email or WhatsApp template to a contact through the outbox (opt-outs, caps and pauses apply).","tags":["templates"],"description":"Sends one template to one person through the outbox, exactly as the team would. Opt-outs, daily caps and paused channels are respected, so a message may be held or blocked rather than sent at once; check its status with messages_list.\n\nReturns { queued, message_id }. queued is false when nothing could be sent, for example because they opted out.","x-permission":"messages:send","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contact_id":{"type":"string","pattern":"^[A-Za-z0-9]{12}$","description":"Who to send to."},"template_id":{"type":"string","pattern":"^[A-Za-z0-9]{12}$","description":"An active template (see templates_list)."}},"required":["contact_id","template_id"]},"example":{"contact_id":"k3Jd9QmZp2Lx","template_id":"Tpl6Wq9Er3Zu"}}}},"responses":{"201":{"description":"{ queued, message_id }. queued is false when nothing could be sent, for example because they opted out.","content":{"application/json":{"example":{"queued":true,"message_id":"Msg3Ui7Op1As"}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"},"404":{"description":"The contact was not found."}}},"get":{"operationId":"messages_list","summary":"The message history, newest first: every email, WhatsApp, SMS, Instagram and Apple message sent or received. Filter by channel, direction, status, supporter or date.","tags":["api"],"description":"Every message sent or received, newest first, with its status and any error. Use it to check what happened to a message from messages_send, or to read someone's conversation.\n\nReturns { data: [message, …], total, limit, offset }.","x-permission":"messages:read","parameters":[{"name":"channel","in":"query","required":false,"schema":{"description":"email, whatsapp, sms, instagram or apple.","type":"string","enum":["email","whatsapp","sms","instagram","apple"]}},{"name":"direction","in":"query","required":false,"schema":{"description":"in for received, out for sent.","type":"string","enum":["in","out"]}},{"name":"status","in":"query","required":false,"schema":{"description":"Only messages with this status.","type":"string","enum":["queued","sending","sent","delivered","read","failed","blocked","dry_run","received"]}},{"name":"contact_id","in":"query","required":false,"schema":{"description":"Only this person's messages.","type":"string","pattern":"^[A-Za-z0-9]{12}$"}},{"name":"since","in":"query","required":false,"schema":{"description":"From this day.","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"until","in":"query","required":false,"schema":{"description":"Up to and including this day.","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"limit","in":"query","required":false,"schema":{"default":50,"type":"integer","minimum":1,"maximum":200}},{"name":"offset","in":"query","required":false,"schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"{ data: [message, …], total, limit, offset }.","content":{"application/json":{"example":{"data":[{"id":"Msg3Ui7Op1As","contact_id":"k3Jd9QmZp2Lx","channel":"email","direction":"out","status":"delivered","recipient":"amina@example.org","subject":"Thank you, Amina","body":"…","template_id":"Tpl6Wq9Er3Zu","automation_id":null,"broadcast_id":null,"error":null,"created_at":"2026-10-04T09:31:00.000Z","sent_at":"2026-10-04T09:31:02.000Z"}],"total":1,"limit":10,"offset":0}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"}}}},"/account":{"get":{"operationId":"account_get","summary":"The organisation this key belongs to: its plan and billing status, the features it has, and the operations this key may call.","tags":["api"],"description":"Who am I? The organisation the key belongs to, its plan and whether it is paused, the features it has and exactly which operations this key may call. A good first call to check a key works.\n\nReturns { organisation, plan, features, key }.","x-permission":"api:manage","parameters":[],"responses":{"200":{"description":"{ organisation, plan, features, key }.","content":{"application/json":{"example":{"organisation":{"id":"Org1Nn2Mm3Bb","name":"Hope Foundation","slug":"hope","timezone":"Europe/London"},"plan":{"id":"growth","name":"Growth","status":"active","trial_ends_at":null,"locked":false,"seats":{"used":4,"limit":10}},"features":["contacts","lists","donations","api"],"key":{"id":"Key9Lk2Jh5Gf","permissions":["contacts:read"],"operations":["contacts_search","contacts_get"]}}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"}}}},"/usage":{"get":{"operationId":"usage_get","summary":"What the organisation used between two dates (default: this calendar month): messages sent and received by channel, workflow runs, API requests, supporters and storage.","tags":["api"],"description":"What the organisation used over a period: messages sent by channel and received, automation runs, API requests, supporters and storage. Dates are in the organisation's time zone.\n\nReturns { from, to, supporters, storage_bytes, messages: { sent, sent_total, received }, workflow_runs, api_requests }.","x-permission":"billing:read","parameters":[{"name":"from","in":"query","required":false,"schema":{"description":"First day; the start of this month if left out.","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"to","in":"query","required":false,"schema":{"description":"Last day, included; now if left out.","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}}],"responses":{"200":{"description":"{ from, to, supporters, storage_bytes, messages: { sent, sent_total, received }, workflow_runs, api_requests }.","content":{"application/json":{"example":{"from":"2026-08-31T23:00:00.000Z","to":"2026-09-30T23:00:00.000Z","supporters":1840,"storage_bytes":5242880,"messages":{"sent":{"email":920,"whatsapp":140},"sent_total":1060,"received":88},"workflow_runs":310,"api_requests":4521}}}},"400":{"description":"Invalid input"},"401":{"description":"No or bad key"},"403":{"description":"Key lacks the feature or permission"}}}}}}