Getting started#
Authentication#
Every request carries an API key in the Authorization header. The account key is found in Myphoner under Manage, then Configure, then Integrations.
Each user also has a personal API key with the same access rights as that user. It lives on the user's preferences page under Credentials.
curl https://<your_subdomain>.myphoner.com/api/v2/lists \
-H "Accept: application/json" \
-H 'Authorization: Token "<your_api_key>"'Treat the key like a password
Anyone who knows your API key can read and change your account through the API. Keep it out of client-side code and public repositories.
Rate limits#
The API allows 60 requests per minute and 300 requests per 5 minutes. Above that the server answers 429 Too Many Requests.
A 429 response carries a Ratelimit-Reset header with the timestamp at which the next request may be made. Wait until at least that time, and back off exponentially if you keep hitting the limit. Clients that ignore 429 responses lose data.
Conventions#
Requests and responses are JSON. Send Accept: application/json and Content-type: application/json on every request.
Resources link to each other through location paths such as /api/v2/leads/98765. Prepend your account subdomain to turn a path into a full URL.
The examples on this page use curl and the fictional demo subdomain. Replace the subdomain, the key and the ids with your own and they can be pasted straight into a terminal.
Manipulating leads and events through the API does not trigger webhooks.
Users#
Invite a user#
POST/api/v2/users
Creates a user and sends them an invitation. The user counts toward your subscription once they accept.
curl -X POST https://demo.myphoner.com/api/v2/users \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"' \
-d '{
"accept_charge_upon_invitation_acceptance": "1",
"user": {
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"listing_ids": ["28885", "29455"]
}
}'{
"id": 6941,
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"created_at": "2017-11-08T10:04:27.822Z",
"updated_at": "2017-11-08T10:04:27.822Z"
}Parameters
| Parameter | Description |
|---|---|
accept_charge_upon_invitation_acceptancestringrequired | Must be "1". Confirms that you understand a new user raises the subscription fee once the invitation is accepted. |
user[email]stringrequired | Email address the invitation is sent to. |
user[first_name]string | |
user[last_name]string | |
user[agent]boolean | Give the user the Agent role. Default true. |
user[users_admin]boolean | Give the user the User manager role. Default false. |
user[lists_admin]boolean | Give the user the Data manager role. Default false. |
user[analyst]boolean | Give the user the Analyst role. Default false. |
user[supervisor]boolean | Give the user the Supervisor role. Default false. |
user[listing_ids]array of integers | Ids of the lists the user can work when they have the Agent role. |
Lists#
List all lists#
GET/api/v2/lists
curl https://demo.myphoner.com/api/v2/lists \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"'[
{
"id": 15288,
"name": "Campaign 1",
"location": "/api/v2/lists/15288",
"created_at": "2016-11-15T12:36:28.024Z",
"locked_on_defaults": true,
"leads_count": 5
},
{
"id": 4146,
"name": "Campaign 2",
"location": "/api/v2/lists/4146",
"created_at": "2015-08-20T11:11:14.394Z",
"locked_on_defaults": false,
"leads_count": 5093
}
]Parameters
| Parameter | Description |
|---|---|
locked_on_defaultsboolean | When true or 1, only lists that guarantee the default fields are returned. |
Create a list#
POST/api/v2/lists
curl -X POST https://demo.myphoner.com/api/v2/lists \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"' \
-d '{
"list": {
"name": "New Campaign",
"columns_attributes": {
"0": { "label": "Name", "kind": "none" },
"1": { "label": "Phone", "kind": "phone" }
}
}
}'{
"id": 29999,
"name": "New Campaign",
"location": "/api/v2/lists/29999",
"created_at": "2017-11-08T10:19:19.643Z",
"locked_on_defaults": false,
"leads_count": 0,
"categories": {}
}Parameters
| Parameter | Description |
|---|---|
list[name]stringrequired | Name of the list. |
list[columns_attributes]object | Fields of the list, keyed by position: {"0": {"label": "Name", "kind": "none"}, "1": {"label": "Phone", "kind": "phone"}}. Each entry takes label, kind and optionally visible. Fields are ordered by their key. kind is one of none (text), phone, email, url, boolean, integer, date, text (multi-line), options or address. |
list[description]string | Call script shown to agents while working the list. |
list[user_ids]array of integers | Ids of agents that get access to the list. |
list[call_back_categories]string | Comma-separated sub-categories for call backs. |
list[winner_categories]string | Comma-separated sub-categories for winners. |
list[loser_categories]string | Comma-separated sub-categories for losers. |
list[archive_categories]string | Comma-separated sub-categories for archived leads. |
list[skip_categories]string | Comma-separated sub-categories for skips. |
list[prepend_phone]boolean | |
list[inline_identifiers]boolean | |
list[show_avatars]boolean | |
list[lock_on_defaults]boolean | |
list[queue_new_before_call_backs]boolean | |
list[queue_new_before_due]boolean | |
list[duplicates_match_on_phone]boolean | |
list[duplicates_match_on_email]boolean | |
list[duplicates_match_on]string |
Retrieve a list#
GET/api/v2/lists/:id
curl https://demo.myphoner.com/api/v2/lists/15288 \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"'{
"id": 15288,
"name": "Campaign 1",
"location": "/api/v2/lists/15288",
"created_at": "2016-11-15T12:36:28.024Z",
"locked_on_defaults": true,
"leads_count": 5,
"categories": {
"call_back": ["sooner", "later"],
"winner": ["bigger", "smaller"]
}
}List the columns of a list#
GET/api/v2/lists/:id/columns
Returns the fields of a list. The key of each column is the name to use when creating, updating or finding leads.
curl https://demo.myphoner.com/api/v2/lists/15288/columns \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"'[
{
"id": 188750,
"key": "first_name",
"label": "First Name",
"type": "unicode",
"input_type": "string",
"required": false
},
{
"id": 188759,
"key": "birthday",
"label": "Birthday",
"type": "datetime",
"input_type": "date",
"required": false
}
]List the leads in a list#
GET/api/v2/lists/:id/leads
Leads are returned newest first by created_at, so you can sync your own records by fetching pages until you meet a lead you already know.
curl https://demo.myphoner.com/api/v2/lists/15288/leads \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"'[
{
"id": 13722815,
"location": "/api/v2/leads/13722815",
"url": "https://demo.myphoner.com/work/leads/13722815",
"list_name": "Campaign 1",
"list_location": "/api/v2/lists/15288",
"primary_identifier": "Craig Tillman",
"secondary_identifier": "nunc nulla",
"tertiary_identifier": "mauris erat eget",
"state": "new",
"category": null,
"scheduled_for": null,
"claimed_by": null,
"claimed_at": null,
"detected_duplicates": [],
"ignored_duplicates": [],
"created_at": "2016-11-15T12:37:25.331Z",
"last_updated": "2016-11-15T12:37:25.331Z",
"lead_data": {
"first_name": "Craig",
"last_name": "Tillman",
"full_name": "Craig Tillman",
"company_name": "mauris erat eget",
"title": "nunc nulla",
"e_mail": "non.justo.Proin@ipsumnunc.ca",
"mobile_phone": "1 35 195 6007-0909",
"work_office_phone": "1 57 733 2671-8905",
"birthday": "1980-06-12 20:10:36"
}
}
]Parameters
| Parameter | Description |
|---|---|
per_pageinteger | Leads per page. Default 50. |
pageinteger | Page number. Default 1. |
orderstring | Set to last_updated_first to sort by last_updated descending instead of created_at. |
Retrieve list statistics#
GET/api/v2/lists/:id/stats
curl https://demo.myphoner.com/api/v2/lists/29455/stats \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"'{
"id": 29455,
"name": "5000leads",
"location": "/api/v2/lists/29455",
"created_at": "2017-10-26T09:34:00.043Z",
"locked_on_defaults": false,
"leads_count": 5099,
"leads_counts": {
"new": { "uncategorised": 5060, "total": 5060 },
"call_back": {
"bad_time": 1,
"positive": 3,
"no_answer": 6,
"voicemail": 2,
"gatekeeper": 0,
"uncategorised": 16,
"total": 28
},
"won": { "uncategorised": 4, "total": 4 },
"lost": { "uncategorised": 5, "total": 5 },
"archived": { "uncategorised": 2, "total": 2 },
"total": 5099
}
}Leads#
Create a lead#
POST/api/v2/lists/:id/leads
Keys in lead are the column keys of the list. Fetch them with list the columns of a list.
curl -X POST https://demo.myphoner.com/api/v2/lists/15288/leads \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"' \
-d '{"lead": {"first_name": "John", "last_name": "Doe", "mobile_phone": "12345678"}}'- The
detected_duplicatesandignored_duplicateskeys hold arrays of lead ids. After uploading an entire new list this information can take up to an hour to settle, depending on the size of the list, because duplicate detection runs in the background. A single lead created through the API has duplicate detection done within a couple of minutes.
Retrieve a lead#
GET/api/v2/leads/:id
Returns a lead in the same shape as list the leads in a list.
curl https://demo.myphoner.com/api/v2/leads/13722811 \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"'- The
detected_duplicatesandignored_duplicateskeys hold arrays of lead ids. After uploading an entire new list this information can take up to an hour to settle, depending on the size of the list, because duplicate detection runs in the background. A single lead created through the API has duplicate detection done within a couple of minutes.
Update a lead#
PATCH/api/v2/leads/:id
Keys in lead are the column keys of the list. Fetch them with list the columns of a list.
curl -X PATCH https://demo.myphoner.com/api/v2/leads/13722820 \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"' \
-d '{"lead": {"full_name": "John Doe", "company_name": "Doe Inc."}}'Responds with 204 No Content on success.
Find leads by field#
GET/api/v2/lists/:id/leads/find
Exact match on one or more fields of the list. By default all supplied fields must match; pass matchall=false to match any of them.
curl "https://demo.myphoner.com/api/v2/lists/15288/leads/find?mobile_phone=15324083898652" \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"'Parameters
| Parameter | Description |
|---|---|
<field_key>string | Value to match. Repeat with different column keys to match on several fields. |
matchallboolean | Set to false to combine conditions with OR instead of AND. |
- The
detected_duplicatesandignored_duplicateskeys hold arrays of lead ids. After uploading an entire new list this information can take up to an hour to settle, depending on the size of the list, because duplicate detection runs in the background. A single lead created through the API has duplicate detection done within a couple of minutes.
Search leads#
GET/api/v2/leads/search
Free-text search across lead data and activity logs, like the search field inside Myphoner.
curl "https://demo.myphoner.com/api/v2/leads/search?query=Houston&list_ids=812,4146" \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"'{
"total": 2,
"leads": []
}Parameters
| Parameter | Description |
|---|---|
querystringrequired | The search string. |
list_idsstring | Comma-separated list ids to scope the search to. |
per_pageinteger | Leads per page. Default 50. |
pageinteger | Page number. Default 1. |
- The
detected_duplicatesandignored_duplicateskeys hold arrays of lead ids. After uploading an entire new list this information can take up to an hour to settle, depending on the size of the list, because duplicate detection runs in the background. A single lead created through the API has duplicate detection done within a couple of minutes.
Mark a lead as winner#
POST/api/v2/leads/:id/winner
curl -X POST https://demo.myphoner.com/api/v2/leads/13722820/winner \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"' \
-d '{"lead": {"call_back_in": "10", "scheduled_for": "2016-06-04 08:04:55 UTC", "comment": "My comment", "category": ""}}'Responds with 204 No Content on success.
Parameters
All parameters are optional.
| Parameter | Description |
|---|---|
call_back_ininteger | Minutes until the scheduled call back. |
scheduled_fordatetime | Time of the call back as YYYY-MM-DD HH:MM:SS UTC. Takes precedence over call_back_in when both are present. See the getting started guide for how a schedule behaves on leads that are not marked for call back. |
commentstring | Text inserted as a comment on the winner event. |
categorystring | Category of the winner event. Must match an existing category exactly, including case. |
Mark a lead for call back#
POST/api/v2/leads/:id/call_back
curl -X POST https://demo.myphoner.com/api/v2/leads/13722820/call_back \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"' \
-d '{"lead": {"call_back_in": "10", "scheduled_for": "2016-06-04 08:04:55 UTC", "comment": "My comment", "category": ""}}'Responds with 204 No Content on success.
Parameters
All parameters are optional.
| Parameter | Description |
|---|---|
call_back_ininteger | Minutes until the scheduled call back. |
scheduled_fordatetime | Time of the call back as YYYY-MM-DD HH:MM:SS UTC. Takes precedence over call_back_in when both are present. See the getting started guide for how a schedule behaves on leads that are not marked for call back. |
commentstring | Text inserted as a comment on the call back event. |
categorystring | Category of the call back event. Must match an existing category exactly, including case. |
Mark a lead as loser#
POST/api/v2/leads/:id/loser
curl -X POST https://demo.myphoner.com/api/v2/leads/13722820/loser \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"' \
-d '{"lead": {"call_back_in": "10", "scheduled_for": "2016-06-04 08:04:55 UTC", "comment": "My comment", "category": ""}}'Responds with 204 No Content on success.
Parameters
All parameters are optional.
| Parameter | Description |
|---|---|
call_back_ininteger | Minutes until the scheduled call back. |
scheduled_fordatetime | Time of the call back as YYYY-MM-DD HH:MM:SS UTC. Takes precedence over call_back_in when both are present. See the getting started guide for how a schedule behaves on leads that are not marked for call back. |
commentstring | Text inserted as a comment on the loser event. |
categorystring | Category of the loser event. Must match an existing category exactly, including case. |
Archive a lead#
POST/api/v2/leads/:id/archive
curl -X POST https://demo.myphoner.com/api/v2/leads/13722820/archive \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"' \
-d '{"lead": {"call_back_in": "10", "scheduled_for": "2016-06-04 08:04:55 UTC", "comment": "My comment", "category": ""}}'Responds with 204 No Content on success.
Parameters
All parameters are optional.
| Parameter | Description |
|---|---|
call_back_ininteger | Minutes until the scheduled call back. |
scheduled_fordatetime | Time of the call back as YYYY-MM-DD HH:MM:SS UTC. Takes precedence over call_back_in when both are present. See the getting started guide for how a schedule behaves on leads that are not marked for call back. |
commentstring | Text inserted as a comment on the archive event. |
categorystring | Category of the archive event. Must match an existing category exactly, including case. |
Delegate or claim a lead#
PATCH/api/v2/leads/:id/delegate
curl -X PATCH https://demo.myphoner.com/api/v2/leads/13722820/delegate \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"' \
-d '{"lead": {"delegate_to": "1250"}}'Responds with 204 No Content on success.
Parameters
| Parameter | Description |
|---|---|
delegate_tointeger or stringrequired | Id or email of the user that should hold the claim on the lead. |
Move a lead to another list#
PATCH/api/v2/leads/:id/migrate
curl -X PATCH https://demo.myphoner.com/api/v2/leads/13722820/migrate \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"' \
-d '{"lead": {"to_list_id": "15288"}}'Responds with 204 No Content on success.
Parameters
| Parameter | Description |
|---|---|
to_list_idintegerrequired | Id of the destination list. May be the current list, which is useful when you only want to release a claimed lead. |
give_back_leadsstring | "1" releases the lead if it is claimed. "0" or omitted leaves the claim as is. |
Calls#
A call is created when an agent dials from Myphoner. Subscribe to the new_call or new_recording webhook to be told when one is available, then fetch it here.
Retrieve a call#
GET/api/v2/calls/:id
curl https://demo.myphoner.com/api/v2/calls/12345 \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"'{
"location": "/api/v2/calls/12345",
"user_email": "agent@example.com",
"destination_number": "+447700900123",
"duration": 11,
"started_at": "2026-09-16T09:31:41.000Z",
"caller_id": { "number": "+442079460000", "name": "Sales line" },
"direction": "outbound",
"disposition": "voicemail",
"state": "completed",
"lead_id": 98765,
"event_id": 54321,
"lead": "/api/v2/leads/98765",
"list": "/api/v2/lists/42",
"recordings": [
{ "started_at": "2026-09-16T09:31:47.000Z", "url": "https://recordings.example.com/abc.wav" }
]
}Response fields
| Field | Description |
|---|---|
locationstring | Path of this call. |
user_emailstring | Email of the agent who made the call. |
destination_numberstring | Number that was dialled. |
durationinteger | Length of the call in seconds. 0 for unanswered and failed attempts. |
started_atstring | When the call started, ISO 8601 in UTC. |
caller_idobject | The outbound caller ID actually used, as {"number": string or null, "name": string or null}. This is the number the recipient saw. With Smart CIDs it varies per call. Always present. |
directionstring | One of outbound, inbound, transfer, local or automated. |
dispositionstring or null | One of busy, failed, invalid_number, normal, no_answer, temp_unavail or voicemail. normal is a connected call the agent ended as a conversation. voicemail is set when the agent uses the voicemail hangup or a Voicemail category while connected. null until the call has been processed. |
statestring | One of initiated, calling, active or completed. |
lead_idinteger or null | Id of the lead this call belongs to. Same lead as the lead link. |
event_idinteger or null | Id of the disposition event on the lead that this call belongs to. null while the call is not yet linked to a disposition. |
leadstring or null | Path of the lead. |
liststring or null | Path of the list the lead is in. |
recordingsarray | Recordings of the call, each with started_at and a url to the audio file. Empty when the call was not recorded. |
- Unanswered and failed attempts are returned too, with
duration0and adispositionsuch asno_answerorbusy. - To attach a lead outcome to a specific call, use
event_idrather than matching on timestamps. - The
new_callwebhook fires only once a call is linked to a lead. Inbound calls are tracked separately and do not firenew_call. A missed inbound callback re-queues the lead and fires thecall_backwebhook instead.
Webhooks#
Subscribe to events such as a new winner, a call back or a finished call and Myphoner sends an HTTP POST to a URL of your choice the moment they happen. The notification tells you where to fetch the full resource.
Webhooks fire on activity inside Myphoner. Changes made through the API do not trigger them.
Events#
The event parameter of a subscription takes one of these values.
| Event | Fires when | Scope |
|---|---|---|
winner | The Winner action was used on a lead. | list |
loser | The Loser action was used on a lead. | list |
archive | The Archive action was used on a lead. | list |
call_back | The Call back action was used on a lead. | list |
text | A text message was sent to a lead. | list |
inbound_text | A text message was received from a lead. | list |
new_event | Any new event, including all of the above, except unclaim and migration. | list |
new_comment | A comment was added to a lead, in any state. | list |
lead_created | An agent created a lead. | list |
lead_updated | An agent changed the lead data of a lead. | list |
new_call | A call was completed and linked to a lead. | list, account |
new_recording | A recorded call was completed. | list, account |
Subscribe to events on a list#
POST/api/v2/lists/:id/webhook
curl -X POST https://demo.myphoner.com/api/v2/lists/15288/webhook \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"' \
-d '{"webhook": {"target_url": "https://yourdomain.com/path/to/endpoint", "event": "winner"}}'Responds with 201 Created on success.
Parameters
| Parameter | Description |
|---|---|
webhook[target_url]stringrequired | URL on your domain that receives the POST described in receive a notification. |
webhook[event]stringrequired | One of the events. |
- The response is the JSON representation of the webhook. Save its
id; you need it to unsubscribe.
Subscribe to events account-wide#
POST/api/v2/webhooks
Only new_call and new_recording can be subscribed account-wide.
curl -X POST https://demo.myphoner.com/api/v2/webhooks \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"' \
-d '{"webhook": {"target_url": "https://yourdomain.com/path/to/endpoint", "event": "new_recording"}}'Responds with 201 Created on success.
Parameters
| Parameter | Description |
|---|---|
webhook[target_url]stringrequired | URL on your domain that receives the POST described in receive a notification. |
webhook[event]stringrequired | new_call or new_recording. |
- The response is the JSON representation of the webhook. Save its
id; you need it to unsubscribe.
Receive a notification#
POST/your/target_urlsent by Myphoner to your server
Myphoner sends this request to the target_url of the subscription. The body names the resource to fetch, which is a lead for lead events and a call for new_call and new_recording.
curl -X POST https://yourdomain.com/path/to/endpoint \
-H "Content-Type: application/json" \
-d '{"resource_url": "https://demo.myphoner.com/api/v2/leads/13722820"}'Parameters
| Parameter | Description |
|---|---|
resource_urlstring | URL of the lead or call the event relates to. |
- Respond with a
200status. The body is ignored.
Responding to errors
Respond with 410 Gone when something is permanently wrong and the subscription should be removed. Any other 4xx or 5xx response is treated as temporary and ignored.
Delete a webhook#
DELETE/api/v2/webhook/:id
curl -X DELETE https://demo.myphoner.com/api/v2/webhook/1234 \
-H "Accept: application/json" \
-H "Content-type: application/json" \
-H 'Authorization: Token "<your_api_key>"'Responds with 200 OK on success.
Parameters
| Parameter | Description |
|---|---|
idintegerrequired | Id of the webhook, returned when you subscribed. |