All integrations

Emelia

BUSINESS · CRM & SUPPORT

Email and LinkedIn campaigns, contacts, and sending mailboxes in that account.

Acts as the person, not as itself

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.

Credentials never touch the agent

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.

Every call on the record

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.

What an agent can do

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.

emelia_delete_advanced_campaigns_by_campaignidWRITE

Delete a campaign via DELETE /advanced/campaigns/{campaignId}. Permanently delete a campaign. The contacts and the contact lists attached to it are not deleted, and stay available for your other campaigns. The campaign must not be `RUNNING`: pause it first with **Pause a campaign**. To keep the campaign and its statistics while removing it from your list, use **Archive a campaign** instead.

api
emelia_delete_linkedin_scrappers_by_idWRITE

Delete a LinkedIn scrapper via DELETE /linkedin-scrappers/{id}.

api
emelia_delete_linkedin_scrappers_by_id_webhookWRITE

Remove a webhook from a scrapper via DELETE /linkedin-scrappers/{id}/webhook.

api
emelia_delete_lists_list_by_listidWRITE

Delete a list via DELETE /lists/list/{listId}. Deletes the list and its contacts.

api
emelia_delete_lists_list_by_listid_rows_by_leadidWRITE

Delete a contact via DELETE /lists/list/{listId}/rows/{leadId}. Deletes a contact from the list (and its company data). The list counters stay in sync, and if the list is used by campaigns the removal is propagated to them. Find the contact's `leadId` with the `email` / `linkedinUrl` lookup of `GET /lists/list/{listId}/rows`. After the delete, Get a contact answers 404 "Lead not found" and a second delete 404 "Contact not found" (measured 2026-09-19).

api
emelia_delete_webhookWRITE

Delete a webhook via DELETE /webhook. Delete an existing webhook by providing its URL Measured 2026-09-19: deleting a URL that is not registered also answers {"success": true} (the operation is idempotent), so confirm the removal with List user webhooks rather than from this status.

api
emelia_get_advanced_campaignsWRITE

List campaigns via GET /advanced/campaigns.

api
emelia_get_advanced_campaigns_by_campaignidWRITE

Get campaign details via GET /advanced/campaigns/{campaignId}. Retrieve the full configuration of a campaign. The response includes the contact lists attached to the campaign (`recipients.lists`) and the lists excluded from it (`recipients.excludedLists`), each with its ID, name and number of contacts. To manage the contacts of an attached list (add, update, search or delete a contact), use the **Lists** endpoints with the list `_id`.

api
emelia_get_advanced_campaigns_by_campaignid_activitiesWRITE

Get campaign activities via GET /advanced/campaigns/{campaignId}/activities.

api
emelia_get_advanced_campaigns_by_campaignid_manual_tasksWRITE

Get pending manual tasks for a campaign via GET /advanced/campaigns/{campaignId}/manual-tasks. Returns the list of pending manual tasks for a given campaign. Optionally filter by step ID.

api
emelia_get_email_providersWRITE

List email providers via GET /email-providers. Returns a list of all email providers for the authenticated user with sensitive data masked

api
emelia_get_email_providers_warmupWRITE

List warmups for all providers via GET /email-providers/warmup. Returns the warmup status for all email providers of the authenticated user

api
emelia_get_linkedin_scrappersWRITE

List all LinkedIn scrappers via GET /linkedin-scrappers.

api
emelia_get_linkedin_scrappers_authesWRITE

List all authes (authentication configurations) via GET /linkedin-scrappers/authes. Returns a list of all LinkedIn authentication configurations for the authenticated user Note that Emelia echoes each configuration's stored LinkedIn `li_at` cookie back in the `token` field of the response (measured 2026-09-19); treat the result as sensitive.

api
emelia_get_linkedin_scrappers_by_id_downloadWRITE

Download scrapper data via GET /linkedin-scrappers/{id}/download.

api
emelia_get_lists_listWRITE

List all lists via GET /lists/list. Without `page` and `limit`, returns a plain array of your lists. With pagination parameters, returns a paginated envelope. Measured 2026-09-19: with no query parameters at all the response is a bare JSON array of lists; with any parameter it is the paginated envelope {items, total, page, pageSize, totalLeads}.

api
emelia_get_lists_list_by_listidWRITE

Get list details via GET /lists/list/{listId}.

api
emelia_get_lists_list_by_listid_rowsWRITE

List contacts of a list via GET /lists/list/{listId}/rows. Paginated listing of the contacts of a list. To check whether a specific contact exists (before updating or deleting it), use the `email` or `linkedinUrl` parameter instead: it returns the exact matches only (email is matched case-insensitively, the LinkedIn URL verbatim), with their `id` usable in the other contact endpoints. These two parameters are mutually exclusive, and take precedence over `search` and the pagination.

api
emelia_get_lists_list_by_listid_rows_by_leadidWRITE

Get a contact via GET /lists/list/{listId}/rows/{leadId}.

api
emelia_get_stats_advancedWRITE

Get campaign statistics via GET /stats/advanced.

api
emelia_get_tools_find_email_by_jobidWRITE

Get the result of a find email job via GET /tools/find/email/{jobId}. An unknown job id answers 400 "Job not found" (measured 2026-09-19).

api
emelia_get_tools_find_phone_by_jobidWRITE

Get the result of a find phone job via GET /tools/find/phone/{jobId}. An unknown job id answers 400 "Job not found" (measured 2026-09-19).

api
emelia_get_tools_verify_email_by_jobidWRITE

Get the result of a verify email job via GET /tools/verify/email/{jobId}. An unknown job id answers 400 "Job not found" (measured 2026-09-19).

api
emelia_get_webhookWRITE

List user webhooks via GET /webhook. Get all webhooks for the authenticated user

api
emelia_patch_advanced_campaigns_by_campaignid_identitiesWRITE

Update campaign identities via PATCH /advanced/campaigns/{campaignId}/identities. Set the identities of a campaign. An identity is a sender: a name, and the accounts it sends from — an email provider and/or a LinkedIn account. Each identity requires a `name` and at least one account: - `email` — ID of one of your email providers, from **List email providers** - `linkedin` — ID of one of your LinkedIn accounts, from **List all authes (authentication configurations)** This endpoint **replaces** the identities of the campaign: send the complete array. The identities are matched by position, and the identities of the campaign beyond the length of the array you send are deleted. An identity reusing an account already used by an earlier identity of the array is ignored. The campaign must not be `RUNNING`: pause it first with **Pause a campaign**. Emelia does not check that an `email` or `linkedin` id exists when the identities are set (measured 2026-09-19: an unowned id is stored and echoed back); the check happens at Start a campaign.

api
emelia_patch_advanced_campaigns_by_campaignid_nameWRITE

Rename a campaign via PATCH /advanced/campaigns/{campaignId}/name. Change the name of a campaign. The campaign must not be `RUNNING`: pause it first with **Pause a campaign**.

api
emelia_patch_advanced_campaigns_by_campaignid_planned_startWRITE

Schedule a campaign start via PATCH /advanced/campaigns/{campaignId}/planned-start. Plan the automatic start of a campaign at a given date, or cancel the plan already registered. The date must be in the future, and the campaign must already be ready to start: the same checks as **Start a campaign** are run when the plan is registered. Send `plannedStart: null` to cancel a plan. DESTRUCTIVE: Scheduling a start makes the campaign send cold email and LinkedIn messages at that date without any further confirmation.

api
emelia_patch_advanced_campaigns_by_campaignid_recipientsWRITE

Update campaign contact lists via PATCH /advanced/campaigns/{campaignId}/recipients. Attach one or several contact lists to a campaign, and optionally exclude lists from it. This endpoint **replaces** the whole selection: send every list ID you want attached, not only the new ones. Use **List all lists** to get the IDs of your lists, and **Get campaign details** to read the current selection (`recipients.lists` and `recipients.excludedLists`). Sending an empty array detaches every list and empties the campaign. The recipients of the campaign are recomputed on the fly: the contacts of the attached lists are de-duplicated by email and LinkedIn profile, and every contact whose email or LinkedIn profile appears in an excluded list is removed. `excludedLists` is optional: when it is omitted, the exclusion lists currently set on the campaign are kept. Unlike the other update endpoints, this one can be called while the campaign is running.

api
emelia_patch_advanced_campaigns_by_campaignid_settingsWRITE

Update campaign settings via PATCH /advanced/campaigns/{campaignId}/settings. Update the general settings of a campaign: daily cadence, sending window, tracking, and the events that stop the sequence for a contact. The settings you send are merged into the current ones, but `start`, `end`, `trackOpens`, `trackLinks` and `blacklistUnsub` must always be present. The safest way to build the payload is to read the current settings with **Get campaign details** (`campaign.schedule`), change the values you need, and send the whole object back. The campaign must not be `RUNNING`: pause it first with **Pause a campaign**. Validation rules: - `end` must be later than `start` - `dailyEmailLimit` must be greater than or equal to `dailyEmailAdded` - `dailyLinkedinAdded` cannot exceed 40 when the sequence contains a connection request step, 80 otherwise

api
emelia_patch_lists_contacts_by_contactidWRITE

Update a contact via PATCH /lists/contacts/{contactId}. Updates a contact from a flat JSON object — the same body as the add endpoint: field names as keys, values as strings, numbers or booleans. Only the contact ID is needed, the list is derived from the contact. Find the ID with the `email` / `linkedinUrl` lookup of `GET /lists/list/{listId}/rows`, or keep the `leadId` returned when you added the contact. Keys are resolved with the same automatic detection as the add endpoint: contact fields, company fields and your custom variables (technical or display name). An unrecognized key automatically creates a new custom variable on your account. The fields you send overwrite the contact's values — every field you don't send stays untouched. If the contact's list is used by campaigns, the updated values are propagated to them.

api
emelia_patch_lists_list_by_listidWRITE

Rename a list via PATCH /lists/list/{listId}.

api
emelia_post_advanced_campaignsWRITE

Create a campaign via POST /advanced/campaigns.

api
emelia_post_advanced_campaigns_by_campaignid_archiveWRITE

Archive a campaign via POST /advanced/campaigns/{campaignId}/archive. Archive a campaign: its status becomes `ARCHIVED` and it is no longer returned by **List campaigns**. Its contacts, activities and statistics are kept. The campaign must not be `RUNNING`: pause it first with **Pause a campaign**. Un-archiving is only available from the application.

api
emelia_post_advanced_campaigns_by_campaignid_duplicateWRITE

Duplicate a campaign via POST /advanced/campaigns/{campaignId}/duplicate. Create a new campaign from an existing one. You choose what is copied; everything not copied keeps the default values of a new campaign. The new campaign is created as a draft, and its name must be free on your account.

api
emelia_post_advanced_campaigns_by_campaignid_manual_tasks_statusWRITE

Set a manual task status via POST /advanced/campaigns/{campaignId}/manual-tasks/status. Mark a pending manual task as completed (ok) or failed (ko) for a specific contact in a campaign.

api
emelia_post_advanced_campaigns_by_campaignid_pauseWRITE

Pause a campaign via POST /advanced/campaigns/{campaignId}/pause. Pause a running campaign and cancel every action already scheduled. The campaign must be `RUNNING`. Pausing a campaign is required before updating its name, its settings, its identities or its steps. Measured 2026-09-19 on a DRAFT campaign: 400 "This campaign must be in RUNNING status to pause it".

api
emelia_post_advanced_campaigns_by_campaignid_startWRITE

Start a campaign via POST /advanced/campaigns/{campaignId}/start. Start a campaign and schedule its first actions. The campaign must have at least one identity, at least one recipient (15,000 maximum), a valid sequence, and the accounts of its identities must be connected. When one of these conditions is not met, the endpoint answers `400` with the reason. DESTRUCTIVE: Starting a campaign sends cold email and LinkedIn messages to every recipient on its schedule; a message sent cannot be unsent. Measured 2026-09-19 on a campaign with no identity: 400 "You must add an an Identity to start the campaign" -- the reason is always in the 400 body.

api
emelia_post_email_providersWRITE

Add a new email provider via POST /email-providers. Creates a new email provider with the provided information Emelia connects to the mailbox before answering, so the SMTP/IMAP or provider credentials must be real (measured 2026-09-19: an unresolvable IMAP host answers 400 "IMAP Error: Cannot resolve IMAP server hostname").

api
emelia_post_email_providers_warmup_disableWRITE

Disable warmup for an email provider via POST /email-providers/warmup/disable. Deactivates the warmup feature for the specified email provider

api
emelia_post_email_providers_warmup_enableWRITE

Enable warmup for an email provider via POST /email-providers/warmup/enable. Activates the warmup feature for the specified email provider

api
emelia_post_linkedin_scrappersWRITE

Create a new LinkedIn scrapper via POST /linkedin-scrappers. `url` must be a LinkedIn Sales Navigator people-search URL; a regular LinkedIn search URL answers 400 "Invalid Sales Navigator URL" (measured 2026-09-19).

api
emelia_post_linkedin_scrappers_authesWRITE

Create a new LinkedIn authentication via POST /linkedin-scrappers/authes. Creates a new LinkedIn authentication configuration with the provided cookies and settings The cookie values are the customer's own LinkedIn session credentials, stored by Emelia to drive the scrapper; Emelia does not validate them at creation time (measured 2026-09-19: a bogus `li_at` is accepted and listed with status "valid").

api
emelia_post_linkedin_scrappers_by_id_enrichWRITE

Start enrichment for a scrapper via POST /linkedin-scrappers/{id}/enrich.

api
emelia_post_linkedin_scrappers_by_id_splitWRITE

Split a LinkedIn scrapper via POST /linkedin-scrappers/{id}/split.

api
emelia_post_linkedin_scrappers_by_id_webhookWRITE

Add a webhook to a scrapper via POST /linkedin-scrappers/{id}/webhook. It triggers when one of the events is triggered. POST request to the webhook URL with the event data as JSON body is sent.

api
emelia_post_lists_listWRITE

Create a list via POST /lists/list. Creates an empty list. Then add your contacts with `POST /lists/list/{listId}/contacts` (or the batch variant).

api
emelia_post_lists_list_by_listid_contactsWRITE

Add a contact to a list via POST /lists/list/{listId}/contacts. Adds a single contact to a list from a flat JSON object — field names as keys, values as strings, numbers or booleans. This is the simplest way to push contacts from your automations (Zapier, Make, n8n...). If the list is used by one or several campaigns, the contact is automatically added to those campaigns. Keys are resolved automatically, with the same detection as a file import (by name, then by content): - contact fields (see the `contact` argument — human-readable names like `First Name` work too), - company fields (`companyName`, `websiteUrl`, `industry`...), - your existing custom variables (by technical or display name). Any unrecognized key automatically creates a new custom variable on your account and stores the value in it. Contact fields: Predefined fields of a contact. They are stored on the contact itself (not as custom variables) and are available as `{{variables}}` in your campaigns. Duplicate detection: If the list already contains a contact with the same `email` or the same `linkedinUrlProfile`, nothing is created: the response returns the existing contact's `leadId` with `duplicate: true`. A criterion only applies when both the payload and the existing contact have a value for it — so a retry of the same call is always safe. With `updateIfExists=true`, a duplicate is updated instead of ignored: the fields of the payload overwrite the existing contact's values (fields you don't send are left untouched), and the response carries `updated: true`. This makes the endpoint a full **add-or-update**.

api
emelia_post_lists_list_by_listid_contacts_batchWRITE

Add contacts in bulk via POST /lists/list/{listId}/contacts/batch. Adds up to **100 contacts** in one call. Each item of `contacts` is the same flat object as the single `POST /lists/list/{listId}/contacts` endpoint, with the same field detection, custom variable auto-creation and duplicate rules (including `updateIfExists`). Rows are processed independently: a failing row is reported in `results` (with its `index` and an `error` message) and does not block the others. A contact repeating an email or LinkedIn URL seen earlier in the same batch is counted as a duplicate.

api
emelia_post_tools_find_emailWRITE

Find email of a single contact via POST /tools/find/email. Starts an asynchronous job and spends Emelia credits; read the result with Get the result of a find email job. On an account with no credits Emelia answers 400 "You do not have enough credits to perform this action" (measured 2026-09-19).

api
emelia_post_tools_find_phoneWRITE

Find phone number of a single contact via POST /tools/find/phone. Starts an asynchronous job and spends Emelia credits; read the result with Get the result of a find phone job. On an account with no credits Emelia answers 400 "You do not have enough credits to perform this action" (measured 2026-09-19).

api
emelia_post_tools_verify_emailWRITE

Verify email of a single contact via POST /tools/verify/email. Starts an asynchronous job and spends Emelia credits; read the result with Get the result of a verify email job. On an account with no credits Emelia answers 400 "You do not have enough credits to perform this action" (measured 2026-09-19).

api
emelia_post_webhookWRITE

Create a webhook via POST /webhook. Create a webhook to watch activity for a campaign

api
emelia_post_webhook_testWRITE

Test a webhook via POST /webhook/test. Trigger a test call to an existing webhook Measured 2026-09-19: the endpoint answers {"success": true} even for a webhook id that does not exist, so a 200 here proves only that the request was accepted -- confirm delivery at the receiving end.

api
emelia_put_linkedin_scrappers_by_id_pauseWRITE

Pause a LinkedIn scrapper via PUT /linkedin-scrappers/{id}/pause.

api
emelia_put_linkedin_scrappers_by_id_renameWRITE

Rename a LinkedIn scrapper via PUT /linkedin-scrappers/{id}/rename.

api
emelia_put_linkedin_scrappers_by_id_resumeWRITE

Resume a LinkedIn scrapper via PUT /linkedin-scrappers/{id}/resume. Requires an active Emelia scrapper subscription: without one Emelia answers 400 "You must have an active subscription to use the scrapper" (measured 2026-09-19).

api

Put Emelia behind one governed endpoint.

Same permissions, same audit trail, whatever else you connect next.