Skip to main content
POST
Log a Call
A call logged here is a call like any other in lemlist: it shows in the contact’s timeline, in the Calls table and in the call stats, it reaches the connected CRM (a Call in HubSpot, a completed Task with its Call Result in Salesforce, a call activity in Pipedrive, as set in Settings → CRM → Activities), and your outgoing webhooks fire for it. The usual flow for a dialer:
  1. Map your outcomes to the team’s call statuses once, from GET /call-statuses.
  2. When a call ends, log it with your own externalId, the rep’s userId, the numbers (from, to), and the task it was made for (taskId, from GET /tasks) or the contact it was with.
  3. When the recording or the transcript lands, send it with PATCH /calls/{id}.
  4. Read the call back with GET /calls/{id} when you need its state, hasRecording first.
Retry on any network error: the same externalId is never logged twice. Send your dialer’s name in provider (for example trellus) on every call: lemlist keeps it to count calls by dialer, while phoneProvider stays api.

What the status does

The automations a call runs come from the status the team configured, not from the status key. lemlist’s default statuses, connected-positive included, only count the call as answered: a status that marks the lead interested or pauses its campaigns is one the team set up so in Settings → Calls. Read the callPositive, callNegative and pausesCampaigns flags of each key from GET /call-statuses before mapping your outcomes, and expect no effect a flag does not announce.

Task or lead

With a taskId, the call completes that task and the sequence moves on, as when a rep marks it done from the dialer. To log a call on a lead without touching its tasks, send leadId (or contactId) instead: the call lands in the timeline and the CRM, the task stays open.

The numbers

from and to take what your telephony reported. A value that reads as a phone number is standardized to E.164 as the contact panel does: its own country code first, else the team’s billing country for a national number. Anything else is kept as sent and never refuses the call: an anonymous caller, an extension, a test number that is no real number such as +15555555555. Only an E.164 finds a contact when to (or from on an inbound call) is the only reference you send.

What the answer guarantees

A 201 (or a 200 on a replay) means the call is stored. Everything that follows runs right after it and is alerted to lemlist when it fails, never answered to you: the push to the CRM, the completion of the task, the status automations, the copy of the recording, the storage of the transcript. A retry answers the stored call and runs none of them again. What you can observe and repair from the API:
  • hasRecording stays false when the recording could not be fetched (an expired or protected URL): send the PATCH again with a reachable URL.
  • The note and the status can be sent again with a PATCH; both reach the CRM call.
  • A call missing from the CRM is on lemlist’s side: lemlist is alerted and looks at it.

Authorizations

Authorization
string
header
required

Basic authentication header of the form Basic <encoded-value>, where <encoded-value> is the base64-encoded string username:password.

Body

application/json
externalId
string
required

Your own id of the call, unique in your dialer. Letters, digits, ., _, : and -, 128 characters at most. The idempotency key: the same id never logs twice, and PATCH /calls/{id} accepts it.

Maximum string length: 128
Pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]*$
Example:

"trellus-8f2c1"

userId
string
required

The lemlist user who made or took the call (usr_…), a member of the team.

Example:

"usr_3Bv7GhT5nJk8Lm2Qx"

direction
enum<string>
required
Available options:
inbound,
outbound
Example:

"outbound"

startedAt
string<date-time>
required

When the call started, ISO 8601. May be in the past; at most 5 minutes in the future.

Example:

"2026-10-21T09:30:00Z"

from
string

The caller's number: the rep's line on an outbound call, the contact's number on an inbound one. Standardized to E.164 as the contact panel does (its own country code, else the team's billing country for a national number) and kept as sent otherwise: an anonymous caller, an extension or a test number that is no real number (+15555555555) never refuses the call. At most 32 characters.

Example:

"+33100000000"

to
string

The number called: the contact's number on an outbound call, the rep's line on an inbound one, standardized like from. On an outbound call its E.164 also finds the contact when no other reference is sent.

Example:

"+33612345678"

duration
integer

Seconds.

Required range: 0 <= x <= 86400
Example:

90

callStatus
string

A key of the team's call statuses (GET /call-statuses). Runs the automations that status carries, as the team configured them: lemlist's default statuses, connected-positive included, only count the call as answered; marking the lead interested or pausing its campaigns comes with a status the team set up so, read its callPositive and pausesCampaigns flags.

Example:

"connected-positive"

note
string

The rep's note on the call: shown with the call in lemlist and written in the CRM call note.

Maximum string length: 10000
Example:

"Asked for a demo next week."

recordingUrl
string<uri>

An https URL of the recording, reachable from the public internet. Fetched in the background. An empty string means no recording.

Maximum string length: 2048
Example:

"https://recordings.dialer.example/8f2c1.mp3"

transcript
string

The transcript as plain text.

Maximum string length: 200000
Example:

"Hi Jane, this is Alex from lemlist…"

provider
string

Your dialer's name, the same on every call you log. lemlist stores it lowercase, apart from phoneProvider (which stays api), to count calls by dialer. An empty string means none.

Maximum string length: 64
Example:

"trellus"

taskId
string

A call task of a campaign (opp_…, from GET /tasks): the call completes it and the sequence moves on. The task's contact and lead are the call's. To log a call on a lead without completing a task, send leadId or contactId instead.

Example:

"opp_9Xw4RtY7kLm2Pq6Zc"

leadId
string

The lead the call was with (lea_…), with its campaign.

Example:

"lea_2Hn8VbQ4wRz6Ym3Jk"

contactId
string

The contact the call was with (ctc_…).

Example:

"ctc_7Ks2PqW9mXb4Lc1Td"

email
string

An email address of the contact the call was with.

Example:

"jane@acme.io"

phone
string

A phone number the call was with: the contact holding it in its phone field. Read as the contact panel reads a number: its own country code, else the team's billing country for a national number. A value that is no number names nobody (CALLS_API_CONTACT_NOT_FOUND).

Example:

"+33612345678"

Response

A call with this externalId was already logged: here it is, unchanged.

success
boolean
Example:

true

data
object

A call logged through POST /calls, as the calls API returns it.