MARKETING · EMAIL
Contacts, lists, campaigns, and reports from the account they connected.
Each user connects their own account. Every call carries both identities — the agent and the person it is acting for — so the agent can never reach past what that individual can already do.
Tokens live in the vault and attach server-side at call time. The agent holds a session, not a secret, and revoking access does not mean rotating a key.
Who asked, which agent acted, which action ran, and the verdict that let it through — one audit trail across every integration, not one per vendor.
Each action is granted on its own. An agent allowed to read is not thereby allowed to write, and the scope beside each row is what the acting user must have connected for it to run at all.
benchmarkemail_delete_api_contact_by_contactidWRITEDelete a contact by id via DELETE /api/contact/{contactId} Answers 200 with the deleted contact object.
benchmarkemail_delete_api_contact_structure_by_contactstructureid_listsWRITEDelete multiple lists via DELETE /api/contact-structure/{contactStructureId}/lists Deletes SEVERAL lists named in the request body, and answers 204. The single-list delete is a different route.
benchmarkemail_delete_api_contact_structure_by_contactstructureid_lists_by_listidWRITEDelete a list by id via DELETE /api/contact-structure/{contactStructureId}/lists/{listId}
benchmarkemail_delete_api_email_campaign_by_campaignidWRITEDelete campaign by id via DELETE /api/email/campaign/{campaignId} Answers 204 with no body.
benchmarkemail_get_api_contactREADGet all contacts via GET /api/contact Returns every contact in one response -- this endpoint does not paginate. Use Search for contacts on a large database.
benchmarkemail_get_api_contact_by_contactidREADGet a contact by id via GET /api/contact/{contactId}
benchmarkemail_get_api_contact_by_contactid_eventsREADGet contact events via GET /api/contact/{contactId}/events
benchmarkemail_get_api_contact_eventsREADGet account contact events via GET /api/contact/events pastDays defaults to 30 and is capped at 90, so this reads a rolling window rather than the full history.
benchmarkemail_get_api_contact_structureREADGet all contact structures via GET /api/contact-structure
benchmarkemail_get_api_contact_structure_by_contactstructureidREADGet a contact structure by id via GET /api/contact-structure/{contactStructureId}
benchmarkemail_get_api_contact_structure_by_contactstructureid_listsREADGet paginated lists via GET /api/contact-structure/{contactStructureId}/lists Page through with page and size; sort takes 'field:direction' over name, createdAt or updatedAt.
benchmarkemail_get_api_contact_structure_by_contactstructureid_lists_allREADGet all lists via GET /api/contact-structure/{contactStructureId}/lists/all The unpaginated companion to Get paginated lists: every list in the structure, id and name only.
benchmarkemail_get_api_contact_structure_by_contactstructureid_lists_by_listidREADGet a list by id via GET /api/contact-structure/{contactStructureId}/lists/{listId}
benchmarkemail_get_api_email_campaignREADGet all campaigns via GET /api/email/campaign
benchmarkemail_get_api_email_campaign_by_campaignidREADGet campaign by id via GET /api/email/campaign/{campaignId}
benchmarkemail_get_api_email_domainREADGet all domains via GET /api/email/domain
benchmarkemail_get_api_email_domain_by_domainidREADGet a domain by id via GET /api/email/domain/{domainId}
benchmarkemail_get_api_email_domain_grey_labelREADGet the grey label domain for the account via GET /api/email/domain/grey-label The account's shared sending domain, used when no authenticated domain of the customer's own is verified.
benchmarkemail_get_api_email_templateREADGet email templates via GET /api/email/template lang is REQUIRED -- the template library is per-language and the call 400s without it.
benchmarkemail_get_api_email_template_by_idREADGet email template by ID via GET /api/email/template/{id} lang is REQUIRED.
benchmarkemail_get_api_email_template_categoriesREADGet email template categories via GET /api/email/template/categories lang is REQUIRED.
benchmarkemail_get_api_reports_dashboardREADGet dashboard snapshot reports via GET /api/reports/dashboard pastDays is REQUIRED (1-90).
benchmarkemail_get_api_reports_email_by_idREADGet individual email campaign reports via GET /api/reports/email/{id}
benchmarkemail_get_api_reports_email_by_id_engagementREADGet individual email campaign engagement reports via GET /api/reports/email/{id}/engagement
benchmarkemail_get_api_reports_email_overallREADGet overall email reports via GET /api/reports/email/overall pastDays is REQUIRED (1-90).
benchmarkemail_get_api_reports_email_overall_histogramREADGet overall email histogram by event type via GET /api/reports/email/overall/histogram pastDays and eventType are both REQUIRED.
benchmarkemail_patch_api_contact_by_contactidWRITEPartial update a contact by id via PATCH /api/contact/{contactId} Accepts the status field only -- every other change goes through Update a contact by id. Status values are case-sensitive, and moving a contact to Inactive requires both primary and secondary. Once Inactive a contact cannot be reactivated through the API.
benchmarkemail_patch_api_contact_structure_by_contactstructureid_lists_by_listidWRITEUpdate a list by id via PATCH /api/contact-structure/{contactStructureId}/lists/{listId}
benchmarkemail_patch_api_email_campaign_by_campaignidWRITEUpdate campaign by id via PATCH /api/email/campaign/{campaignId}
benchmarkemail_post_api_contactWRITECreate a new contact via POST /api/contact key is the contact's email address and contactStructureId decides which custom fields exist; fields entries reference a field's _id from the contact structure. A duplicate email in the same structure is a 400 DuplicateFieldError, not a second contact.
benchmarkemail_post_api_contact_exportWRITEExport contacts via POST /api/contact/export Answers text/csv rather than JSON; the connector returns the CSV under a raw key when the body does not parse as JSON.
benchmarkemail_post_api_contact_searchWRITESearch for contacts via POST /api/contact/search A read expressed as a POST because the filter travels in the body. It needs contacts:read, not contacts:write.
benchmarkemail_post_api_contact_structureWRITECreate a new contact structure via POST /api/contact-structure
benchmarkemail_post_api_contact_structure_by_contactstructureid_listsWRITECreate a new list via POST /api/contact-structure/{contactStructureId}/lists
benchmarkemail_post_api_contact_structure_by_contactstructureid_lists_by_listid_duplicateWRITEDuplicate a list via POST /api/contact-structure/{contactStructureId}/lists/{listId}/duplicate
benchmarkemail_post_api_contact_structure_by_contactstructureid_lists_mergeWRITEMerge lists into a new list via POST /api/contact-structure/{contactStructureId}/lists/merge Creates a NEW list from the named sources; the sources themselves are not consumed.
benchmarkemail_post_api_email_campaignWRITEAdd a campaign via POST /api/email/campaign
benchmarkemail_post_api_email_campaign_by_campaignid_duplicateWRITEDuplicate an existing campaign via POST /api/email/campaign/{campaignId}/duplicate The copy is created as a draft; duplicating never sends.
benchmarkemail_put_api_contact_by_contactidWRITEUpdate a contact by id via PUT /api/contact/{contactId} A REPLACE: any field omitted from the body is removed from the stored contact. __v is required and must come from a fresh Get a contact by id; a stale value is refused with 400 ConcurrencyError. Cannot move an Inactive contact back to Active.
benchmarkemail_put_api_contact_structure_by_contactstructureidWRITEUpdate a contact structure by id via PUT /api/contact-structure/{contactStructureId} Removing a field that a sign-up form still references is refused with 400 ContactFieldInUseError, whose debug.affectedForms names each form.
Put Benchmark Email behind one governed endpoint.
Same permissions, same audit trail, whatever else you connect next.