جهات الاتصال
كل عملية في هذه المجموعة: ما تقبله وما تُرجعه والأخطاء التي قد تردّ بها.
العمليات
The address book, and it belongs to the workspace rather than to whoever saved a row. Every member and every key on the workspace reads and writes the same book.
A contact is addressed by its email address on every route here, because no id is exposed. Two things write rows: somebody saving one, in the app or through this API, which lands as manual, and a member sending mail from the app composer, which lands as auto. Mail ARRIVING from an address creates nothing, so an empty book on a busy mailbox is the expected state rather than a fault.
GET/contacts
List contacts
The address book belongs to the workspace, so every key on it reads the same rows and a contact saved by one member is visible to the rest.
Most recently seen first, with contacts that have never been mailed last. source is manual for an address somebody saved, in the app or through this API, and auto for one recorded because a member sent mail to it from the composer. Mail arriving from an address creates no contact.
Paging is keyset. Pass nextCursor back as cursor while hasMore is true.
Requires the contacts:read scope.
معلمات الاستعلام
limitintegerRows per page, a whole number from 1 to 200. The server defaults to 50.
على الأقل 1على الأكثر 200الافتراضي50cursorstringThe
nextCursorfrom the previous page. Never build one yourself.sourcestringNarrows the page to contacts recorded that way.
أحد"manual""auto""form"qstringSearches the name and the address. When nothing matches exactly on the first page, close spellings are returned instead, and the pages that follow keep matching the same way.
حتى 200 من الأحرف
يُرجع
Contacts in this workspace.
الأخطاء
الأخطاء التي يمكن أن تُرجعها أي عملية400401403404422500دليل الأخطاء
متاح أيضًا في
POST/contacts
Create a contact
The address is the identity, so there is no id to choose and no id in the response. It is trimmed and lower cased before it is stored, and the contact is saved with source set to manual.
The new contact joins the built-in default audience as it is written, and any audience named in audienceIds alongside it. Naming audiences also requires the audiences:write scope.
An address already in the book is refused rather than merged, so a retry cannot overwrite a name somebody edited in the app.
Requires the contacts:write scope.
متن الطلب
emailstringمطلوبTrimmed and lower cased before it is stored.
حتى 320 من الأحرفالتنسيقemailnamestringDisplay name. Leave it out to save the contact without one.
يمكن أن يكون nullحتى 200 من الأحرفnotesstringFree text kept with the contact and shown beside it in the app.
يمكن أن يكون nullحتى 5000 من الأحرفaudienceIdsstring[]Audiences to put the new contact in. The default audience is joined whether or not it is named here. Sending this also requires the
audiences:writescope.حتى 25 من العناصر
يُرجع
Created.
الأخطاء
- 409
contact_exists: that address is already in this workspace book. PATCH it instead.
الأخطاء التي يمكن أن تُرجعها أي عملية400401403404422500دليل الأخطاء
متاح أيضًا في
GET/contacts/people
List people
Everyone on the Contacts page in the app: the saved contacts, and every address seen in mail as the sender or a recipient of a thread's newest message, with the number of threads and when mail last moved. A person seen in mail and saved is one row.
The addresses seen in mail are listed only when the key also holds threads:read, because they are read out of the mail. Without it the rows are the saved contacts alone and seen is false. A key limited to particular addresses or domains gets the saved contacts alone too, with seen false, even when it holds threads:read, because the other addresses would be read out of the mail of every address in the workspace. Deleted addresses and the mailbox's own addresses are left out.
blockedBy names the workspace blocklist rule that blocks a row, the same rule blocked=true filters on.
Requires the contacts:read scope.
معلمات الاستعلام
limitintegerRows per page, 1 to 100.
على الأقل 1على الأكثر 100الافتراضي25cursorstringAn opaque cursor from the previous page, with the same
sort,qandblocked. Keyset, not offset: pass the previous page'snextCursor. One that names nothing in this list is a 400invalid_cursor.sortstringrecentputs the newest mail first, then saved contacts never seen in mail.namegoes by name, or by address where there is none, ignoring case.threadsputs the people with the most threads first.أحد"recent""name""threads"الافتراضي"recent"qstringSearches names, addresses and notes, with close spellings when nothing matches exactly.
حتى 200 من الأحرفemailstringOne address only, matched case insensitively: the way to read one person's thread count and last mail.
حتى 320 من الأحرفblockedstringtruefor only the people the workspace blocklist blocks, whole-domain rules included.أحد"true""false"
يُرجع
A page of people.
الأخطاء
الأخطاء التي يمكن أن تُرجعها أي عملية400401403404422500دليل الأخطاء
متاح أيضًا في
POST/contacts/batch-delete
Delete contacts in bulk
Deletes up to 200 addresses in one call, each the way DELETE /contacts/{email} deletes one: a saved contact goes with its notes, photo and audience memberships, and every address is hidden, so a send does not record it again. Addresses that were only seen in mail are hidden too. An entry that is not an address comes back in invalid and the rest still go through.
Requires the contacts:write scope.
متن الطلب
emailsstring[]مطلوبAddresses, matched case insensitively. A repeated address counts once.
من 1 إلى 200 من العناصر
يُرجع
What was deleted.
الأخطاء
الأخطاء التي يمكن أن تُرجعها أي عملية400401403404422500دليل الأخطاء
متاح أيضًا في
GET/contacts/{email}
Retrieve a contact
The book is the workspace's. The address is matched case insensitively, and it is a path segment, so URL encode it: [email protected] travels as grace%40example.com.
A 404 means only that the address is not in the book. It says nothing about whether mail has been exchanged with it.
Requires the contacts:read scope.
معلمات المسار
emailstringمطلوبThe contact's address, matched case insensitively.
يُرجع
The contact.
الأخطاء
الأخطاء التي يمكن أن تُرجعها أي عملية400401403404422500دليل الأخطاء
متاح أيضًا في
PATCH/contacts/{email}
Update a contact
A partial update, never an upsert. An address not in the book is a 404.
The address itself cannot be changed: it is the identity and the path segment, so moving a contact to a new address is a delete and a create. source and lastSeenAt are the server's and are not accepted here.
Requires the contacts:write scope.
معلمات المسار
emailstringمطلوبThe contact's address, matched case insensitively.
متن الطلب
namestringNew display name. Null clears it.
يمكن أن يكون nullحتى 200 من الأحرفnotesstringNew notes. Null clears them.
يمكن أن يكون nullحتى 5000 من الأحرف
يُرجع
Saved.
الأخطاء
الأخطاء التي يمكن أن تُرجعها أي عملية400401403404422500دليل الأخطاء
متاح أيضًا في
PUT/contacts/{email}
Save a contact
Saves the address the way Add to contacts and Keep in contacts do in the app. An address that is not a contact yet becomes one, answered with 201. One recorded from a send becomes manual, and one already saved keeps what it has, answered with 200. A deleted address is brought back. The body is optional.
Requires the contacts:write scope.
معلمات المسار
emailstringمطلوبThe address, trimmed and lower cased on the server.
متن الطلب
namestringUp to 200 characters. Left out, the stored name is kept.
حتى 200 من الأحرفnotesstringUp to 5,000 characters.
nullclears the notes; left out, they are kept.يمكن أن يكون nullحتى 5000 من الأحرف
يُرجع
Already a contact, now kept as manual.
Saved as a new contact.
الأخطاء
- 422
unknown_parameterfor any key butnameandnotes.
الأخطاء التي يمكن أن تُرجعها أي عملية400401403404500دليل الأخطاء
متاح أيضًا في
DELETE/contacts/{email}
Delete a contact
Deletes somebody from the contacts the way Delete does in the app. A saved contact goes with its notes, its photo and every audience membership, the built-in default one included. The address is then hidden: it leaves GET /contacts/people, and mail sent to it from the app composer no longer records it. The address can be one that was only ever seen in mail.
No mail moves. Saving the address again, with POST /contacts or PUT /contacts/{email}, brings it back as a new contact.
Requires the contacts:write scope.
معلمات المسار
emailstringمطلوبThe contact's address, matched case insensitively.
يُرجع
Deleted and hidden.
الأخطاء
- 422
invalid_contactwhen the path is not an address.
الأخطاء التي يمكن أن تُرجعها أي عملية400401403404500دليل الأخطاء
متاح أيضًا في
PUT/contacts/{email}/photo
Set a contact photo
Uploads the photo shown for the contact, replacing any there was. Send the image itself as the body, not JSON, with its type in Content-Type: image/png, image/jpeg, image/webp, image/gif. Up to 5 MB goes in. It is fitted into a 512 pixel square and stored as WebP, and an animated image keeps its first frame.
The address has to be a saved contact: save it with PUT /contacts/{email} first.
Requires the contacts:write scope.
معلمات المسار
emailstringمطلوبThe contact's address, matched case insensitively.
متن الطلب
نوع المحتوىimage/png, image/jpeg, image/webp, image/gif
يُرجع
The contact, with its new photoUrl.
الأخطاء
- 404
contact_not_foundonemail: the address is not a saved contact.- 422
invalid_imagewhen the body is not an image of an accepted type, is too large or cannot be read.- 502
image_not_stored: the image was read but could not be stored. Try again.- 503
image_busy: the image service is saturated. Try again shortly.
الأخطاء التي يمكن أن تُرجعها أي عملية400401403500دليل الأخطاء
متاح أيضًا في
DELETE/contacts/{email}/photo
Remove a contact photo
Removes the contact photo and deletes the stored image. Removing a photo from a contact that has none changes nothing.
Requires the contacts:write scope.
معلمات المسار
emailstringمطلوبThe contact's address, matched case insensitively.
يُرجع
The contact, with photoUrl null.
الأخطاء
- 404
contact_not_foundonemail: the address is not a saved contact.
الأخطاء التي يمكن أن تُرجعها أي عملية400401403422500دليل الأخطاء
متاح أيضًا في
POST/contacts/{email}/block
Block a contact
Puts the address on the workspace blocklist, the one PATCH /settings edits as blockedSenders, so mail from it is refused from then on. A plus tag is dropped: blocking [email protected] blocks [email protected]. When a rule already blocks the address, a whole-domain one included, nothing is added and created is false. The address does not have to be a contact.
It needs settings:write, because it writes the blocklist rather than the contact.
Requires the settings:write scope.
معلمات المسار
emailstringمطلوبThe address to block.
يُرجع
Blocked.
الأخطاء
- 422
invalid_contactwhen the path is not an address,blocklist_entry_too_broadwhen it has fewer than two letters or numbers, or the narrowed-key refusal.capability_unsupportedonaddressAllowlist: the blocklist belongs to the whole workspace and filters the mail of every address in it, so a key limited to particular addresses or domains cannot change it. Use a key with no address or domain restriction.
الأخطاء التي يمكن أن تُرجعها أي عملية400401403404500دليل الأخطاء
متاح أيضًا في
DELETE/contacts/{email}/block
Unblock a contact
Takes every workspace blocklist rule that blocks the address off the list, and lists them in removed. When one is a whole-domain rule, everybody at that domain is unblocked with it. Rules set for one address or one domain in the settings are not touched. An address no rule blocks answers with removed empty.
Requires the settings:write scope.
معلمات المسار
emailstringمطلوبThe address to unblock.
يُرجع
Unblocked.
الأخطاء
- 422
invalid_contactwhen the path is not an address, or the narrowed-key refusal.capability_unsupportedonaddressAllowlist: the blocklist belongs to the whole workspace and filters the mail of every address in it, so a key limited to particular addresses or domains cannot change it. Use a key with no address or domain restriction.
الأخطاء التي يمكن أن تُرجعها أي عملية400401403404500دليل الأخطاء
متاح أيضًا في
GET/contacts/{email}/threads
List conversations with a contact
Every thread the address wrote or was written to, in every folder, the Mail tab on a contact in the app. The address does not have to be a saved contact. Each row is a summary of the thread; GET /threads/{id} reads the messages.
Requires the threads:read scope.
معلمات المسار
emailstringمطلوبThe address. It does not have to be a saved contact.
معلمات الاستعلام
limitintegerThreads per page, 1 to 100.
على الأقل 1على الأكثر 100الافتراضي25cursorstringThe previous page's
nextCursor, with the sameqandsort.qstringSearches inside those threads, with the same syntax as the mailbox search.
حتى 200 من الأحرفsortstringnewest(the default),oldest,senderorsubject.أحد"newest""oldest""sender""subject"الافتراضي"newest"
يُرجع
A page of threads.
الأخطاء
- 422
invalid_contactwhen the path is not an address, or the narrowed-key refusal.capability_unsupportedonaddressAllowlist: a contact's threads and activity are read from the mail of every address in the workspace, so a key limited to particular addresses or domains cannot read them. Use a key with no address or domain restriction.
الأخطاء التي يمكن أن تُرجعها أي عملية400401403404500دليل الأخطاء
متاح أيضًا في
GET/contacts/{email}/activity
Read activity with a contact
The Activity tab on a contact in the app: messages received from the address and sent to it, per bucket, over a window that ends now, with the threads that moved, the threads waiting on a reply from the mailbox, and the median time each side takes to answer. Mail in the bin or in spam is left out.
Requires the threads:read scope.
معلمات المسار
emailstringمطلوبThe address. It does not have to be a saved contact.
معلمات الاستعلام
minutesintegerHow far back the window reaches from now. The default is 90 days.
على الأقل 1على الأكثر 10540800الافتراضي129600grainstringBucket width:
minute,hourorday, defaulting today.أحد"minute""hour""day"الافتراضي"day"offsetMinutesintegerThe reader's offset from UTC in minutes, so that a day bucket falls on their calendar.
على الأقل -840على الأكثر 840الافتراضي0
يُرجع
The activity.
الأخطاء
- 422
invalid_contactwhen the path is not an address, or the narrowed-key refusal.capability_unsupportedonaddressAllowlist: a contact's threads and activity are read from the mail of every address in the workspace, so a key limited to particular addresses or domains cannot read them. Use a key with no address or domain restriction.
الأخطاء التي يمكن أن تُرجعها أي عملية400401403404500دليل الأخطاء
متاح أيضًا في
PUT/contacts/{email}/audiences
Set a contact's audiences
Sets exactly which audiences the contact is in, the way the audience picker on a contact does in the app. The contact joins every listed audience it is not in yet and leaves every other one, in one transaction. The built-in default audience is always kept, so { "audienceIds": [] } leaves the contact in the default audience alone. Memberships it keeps also keep their addedAt.
The address is matched case insensitively and has to be a contact already. Create it with POST /contacts, which takes audienceIds too. An id that names no audience in this workspace refuses the whole call and changes nothing.
audiences:write is the only scope checked, because this writes memberships rather than the contact. Sending the same list again changes nothing, so a retry is safe.
Requires the audiences:write scope.
معلمات المسار
emailstringمطلوبThe contact's address, matched case insensitively.
متن الطلب
audienceIdsstring[]مطلوبEvery audience the contact should be in once the call returns, up to 100. The default audience is kept whether or not it is named, so an empty array leaves only the default one. A repeated id counts once.
حتى 100 من العناصر
يُرجع
The contact, with the audiences it is in after the change.
الأخطاء
- 404
contact_not_foundonemailwhen the address is not in the workspace book, oraudience_not_foundonaudienceIdswhen an id names no audience here. Nothing is changed.- 422
invalid_parameteronaudienceIdsfor more than 100 ids, and on the entry, such asaudienceIds.0, for an empty one,unknown_parameterfor any other key in the body.
الأخطاء التي يمكن أن تُرجعها أي عملية400401403500دليل الأخطاء
متاح أيضًا في
الكائنات
Contactobject
objectstring- أحد
"contact" emailstringTrimmed and lower cased on write. This is the key every contact route takes, because no contact id is exposed.
namestring- يمكن أن يكون null
sourcestringautowhen a send from the app composer recorded the address,manualwhen somebody saved it here or in the app. A recorded send never downgrades amanualcontact toauto.أحد"manual""auto""form"notesstring- يمكن أن يكون null
photoUrlstringWhere the contact photo is served, or null when the contact has none. Set it with
PUT /contacts/{email}/photo. A new upload gets a new URL.يمكن أن يكون nulllastSeenAtstringWhen mail last went to this address from the app composer. Null until it does.
يمكن أن يكون nullالتنسيقdate-timecreatedAtstring- التنسيق
date-time updatedAtstring- التنسيق
date-time
ContactActivityobject
objectstring- أحد
"contact_activity" emailstringsincestringThe start of the first bucket, on the boundary
grainandoffsetMinutesput it.التنسيقdate-timeuntilstring- التنسيق
date-time grainstring- أحد
"minute""hour""day" bucketsobject[]Only the buckets with mail in them, oldest first.
bucketstringThe bucket in the reader's time:
2026-09-23,2026-09-23T14or2026-09-23T14:05.receivedintegerMessages from this address.
sentintegerMessages from the mailbox to this address.
totalsobjectreceivedintegersentintegerthreadsintegerThreads with at least one message in the window.
waitingintegerThreads whose newest message is from this address, so the mailbox owes the reply.
lastReceivedAtstring- يمكن أن يكون nullالتنسيق
date-time lastSentAtstring- يمكن أن يكون nullالتنسيق
date-time
replyTimeobjectyoursnumberMedian milliseconds the mailbox took to answer, or null without a reply to measure.
يمكن أن يكون nulltheirsnumberMedian milliseconds this address took to answer.
يمكن أن يكون null
ContactBatchDeleteobject
objectstring- أحد
"contact_batch_delete" deletedintegerAddresses deleted and hidden, saved or not.
savedintegerOf those, how many were saved contacts.
invalidstring[]Entries that are not addresses, lower cased. Nothing happened to them.
ContactBlockobject
objectstring- أحد
"contact_block" emailstringThe address as the blocklist sees it: lower cased, with any plus tag dropped.
blockedbooleanblockedByobjectOn a block, the rule that now blocks the address.
يمكن أن يكون nullrulestringThe entry on the workspace blocklist that matches this address, exactly as it is stored.
liststringblockedSendersfor an address or pattern rule,blockedDomainsfor a rule that blocks a whole domain and every subdomain under it.أحد"blockedSenders""blockedDomains"
createdbooleanOn a block, false when a rule already blocked the address and nothing was added.
removedobject[]On an unblock, every rule taken off the workspace blocklist. A
blockedDomainsentry here unblocked the whole domain.rulestringThe entry on the workspace blocklist that matches this address, exactly as it is stored.
liststringblockedSendersfor an address or pattern rule,blockedDomainsfor a rule that blocks a whole domain and every subdomain under it.أحد"blockedSenders""blockedDomains"
ContactDetailobject
objectstring- أحد
"contact" emailstringTrimmed and lower cased on write. This is the key every contact route takes, because no contact id is exposed.
namestring- يمكن أن يكون null
sourcestringautowhen a send from the app composer recorded the address,manualwhen somebody saved it here or in the app. A recorded send never downgrades amanualcontact toauto.أحد"manual""auto""form"notesstring- يمكن أن يكون null
photoUrlstringWhere the contact photo is served, or null when the contact has none. Set it with
PUT /contacts/{email}/photo. A new upload gets a new URL.يمكن أن يكون nulllastSeenAtstringWhen mail last went to this address from the app composer. Null until it does.
يمكن أن يكون nullالتنسيقdate-timecreatedAtstring- التنسيق
date-time updatedAtstring- التنسيق
date-time audiencesobject[]Every audience this contact is in, the built-in default one included. Single-contact responses carry it; the list route does not.
idstringThe audience handle,
aud_plus 24 hex.namestringbuiltinstringdefaulton the one audience every contact joins, null on an audience somebody created.يمكن أن يكون nullأحد"default"
ContactListobject
objectstring- أحد
"list" dataContact[]hasMorebooleannextCursorstring- يمكن أن يكون null
ContactThreadobject
objectstring- أحد
"thread" idstringThe id
GET /threads/{id}takes.subjectstring- يمكن أن يكون null
fromobjectWho sent the newest message.
يمكن أن يكون nullnamestring- يمكن أن يكون null
emailstring
receivedAtstringWhen the newest message arrived or went out.
يمكن أن يكون nullmessageCountintegerhasUnreadbooleanlabelsobject[]idstringnamestring
ContactThreadListobject
objectstring- أحد
"list" dataContactThread[]hasMorebooleanTrue when another page follows. Pass
nextCursorback ascursorto read it.nextCursorstringOpaque. Pass it back as
cursorfor the next page, and never build one yourself.يمكن أن يكون null
DeletedContactobject
objectstring- أحد
"contact" emailstringdeletedboolean- أحد
true wasSavedbooleanTrue when a saved contact was removed, false when the address was only seen in mail and has now been hidden.
Personobject
objectstring- أحد
"person" emailstringLower cased. The key every contact route takes.
displayEmailstringThe address as the most recent message wrote it, which may carry capitals.
namestringThe saved name, or else the newest display name seen in mail.
يمكن أن يكون nullsavedbooleanTrue when the address is a saved contact.
sourcestringAs on a contact, or null when the address is only seen in mail.
يمكن أن يكون nullأحد"manual""auto""form"notesstring- يمكن أن يكون null
photoUrlstring- يمكن أن يكون null
threadsintegerHow many threads have this address as the sender or a recipient of their newest message. Null when the key does not read mail or the address has never been seen in it.
يمكن أن يكون nulllastAtstringWhen the newest of those threads last moved. Null for a saved contact never seen in mail.
يمكن أن يكون nullالتنسيقdate-timecreatedAtstring- يمكن أن يكون nullالتنسيق
date-time updatedAtstring- يمكن أن يكون nullالتنسيق
date-time blockedByobjectThe workspace blocklist rule that blocks this address, or null when none does.
يمكن أن يكون nullrulestringThe entry on the workspace blocklist that matches this address, exactly as it is stored.
liststringblockedSendersfor an address or pattern rule,blockedDomainsfor a rule that blocks a whole domain and every subdomain under it.أحد"blockedSenders""blockedDomains"
PersonListobject
objectstring- أحد
"list" dataPerson[]hasMorebooleanTrue when another page follows. Pass
nextCursorback ascursorto read it.nextCursorstringOpaque. Pass it back as
cursorfor the next page, and never build one yourself.يمكن أن يكون nullseenbooleanTrue when the addresses seen in mail are included, which needs
threads:read. False means the rows are the saved contacts alone.