RingPlan API
Scroll down for code samples, example requests and responses.
Welcome to documentation for RingPlan API.
The current API URL is https://ssp-backend.ringplan.com.
RingPlan API is built upon REST
and each request is based on the HTTP methods of GET, PUT, POST, PATCH and DELETE.
All you need to have in order to access the API is an HTTP client capable of using these methods,
setting HTTP headers as well as sending JSON payloads.
In addition, RingPlan provides a WebSocket API.
Example Python snippets using the requests library
are provided for you in the column on the right.
WebSocket examples are given in JavaScript using the Socket.IO library.
This document is structured in the following main sections:
Overview, which you are reading right now, explaining the structure of the document.
Guides, containing tutorials and walkthroughs for common use-cases of this API.
REST, for descriptions of REST API endpoints with examples.
WebSocket, for descriptions of WebSocket API endpoints with examples.
Objects, where fields and uses of internal objects are described.
Guide
Example request headers for a specific contact
API_KEY = 'secret_string'
headers = {
'Authorization': 'Bearer ' + API_KEY
'X-User-Id': '60190ce750fe88ed1a544a7a'
}
Example request headers for the primary contact
API_KEY = 'secret_string'
headers = {
'Authorization': 'Bearer ' + API_KEY
'X-User-Id': 'primary'
}
RingPlan REST API supports OAuth-based authentication,
using the Authorization header, whose value must be Bearer followed by the company's API key.
API keys can be obtained from the Self Service Portal.
Each API key is tied to a single company.
The user sending the request provides their contact id with the X-User-Id header.
Each company has a special user with administrator permissions named primary.
Any user in the company (including the primary user) can be impersonated with the X-User-Id header.
REST
Constant values for examples
import requests
API_URL = 'https://ssp-backend.ringplan.com'
API_KEY = 'secret string'
USER_ID = 'id of acting user'
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer ' + API_KEY,
'X-User-Id': USER_ID
}
Each endpoint supplies status codes in conformance with RFC 7231.
Endpoint return values are described in the Responses section. If they return ad hoc objects, the fields are described separately under said section.
Error messages are always in the following format:
| Field | Type | Description | Example |
|---|---|---|---|
detail |
string | Error message | "The requested URL was not found on the server." |
status |
integer | Status code | 404 |
title |
string | Status message | "Not Found" |
type |
string | Miscellaneous information | "about:blank" |
All methods will return 401 Unauthorized for failed authorization due to
invalid or missing API_KEY or X-User-Id headers.
Company
company endpoints
Get company information
Get the current company
request = requests.get(API_URL + '/system/company', headers = headers)
print(request.json())
GET /system/company
Return the company object of the company the given user belongs to.
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | company object successfully returned. |
Update company
Update the current company
headers['X-User-Id'] = 'primary'
body = {
'name': 'New Company',
'email': 'new@example.net'
}
request = requests.patch(API_URL + '/company', headers = headers, json = body)
print(request.json())
PATCH /company
Partially update the company the current user belongs to.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| body | body | company object |
true | Partial or full company object |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | company successfully updated and returned. |
| 403 | Forbidden | Requesting user is not the company owner. |
Users
contact endpoints
Get users in company
Return users in current company with given work email
query = {
'work_email': 'sales@example.com'
}
request = requests.get(API_URL + '/system/company/contacts', headers = headers, params = query)
print(request.json())
GET /system/company/contacts
Return the list of users that share the same company as the current user,
optionally filtered and sorted by query parameters.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
first_name |
query | string | false | Filter by first_name |
work_email |
query | string | false | Filter by work_email |
items_per_page |
query | integer | false | Number of contacts per page |
page |
query | integer | false | Index of the page of contacts (default 1) |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | An array of contacts successfully returned. |
| 204 | No Content | There are no contacts with provided query filters. |
| 400 | Bad Request | Invalid parameter provided. |
Add user to company
Add new user to current company
headers['X-User-Id'] = 'primary'
body = {
'first_name': 'Jane',
'contacts': {
'email': 'janedoe@example.com'
}
}
request = requests.post(API_URL + '/company/contacts', headers = headers, json = body)
print(request.json())
POST /company/contacts
Create a new user, add it to the current company and return the contact object.
Only the company owner, i.e the primary user, is allowed to create new users.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| body | body | contact object |
true | contact to be added to the company |
Responses
| Status | Meaning | Description |
|---|---|---|
| 201 | Created | A contact was successfully created and returned. |
| 400 | Bad Request | Provided user information could not be validated. |
| 403 | Forbidden | User is not the owner of this company. |
Update user
Updating a user's details
contact_id = '60190ce750fe88ed1a544a7a'
headers['X-User-Id'] = contact_id
body = {
'emergency_contact_number': '15554441234',
'last_name': 'Smith'
}
request = requests.patch(API_URL + '/company/contacts/' + contact_id, headers = headers, json = body)
print(request.json())
PATCH /company/contacts/{contact_id}
Partially update contact with the provided contact_id and return the updated contact object.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
contact_id |
path | contact id string |
true | ID of the contact to be updated |
| body | body | contact object |
true | Partial or full contact object |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | contact successfully updated and returned. |
| 400 | Bad Request | Invalid parameters in the payload. |
| 403 | Forbidden | Requesting user is neither the one being updated nor the company owner. |
| 404 | Not Found | contact with the given ID does not exist. |
Delete user
Deleting a user from the company
contact_id = '60190ce750fe88ed1a544a7a'
headers['X-User-Id'] = 'primary'
request = requests.delete(API_URL + '/company/contacts/' + contact_id, headers = headers)
print(request.json())
DELETE /company/contacts/{contact_id}
Delete the given user in the current company.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
contact_id |
path | contact id string |
true | contact to be deleted. |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | contact successfully deleted. |
| 403 | Forbidden | Requesting user is not the company owner. |
| 404 | Not Found | contact with the given ID does not exist. |
Locations
location endpoints
Get company locations
Get the list of locations belonging to the company
request = requests.get(API_URL + '/company/locations', headers = headers)
print(request.json())
GET /company/locations
Return the list of locations for the current company.
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | An array of locations successfully returned. |
Add location to company
Add a second location to the company
body = {
'name': 'Second Location',
'country': 'United States',
'state': 'California',
'city': 'Carlsbad',
'zip': '92008',
'company_id': '611ced1255c44a89f8df7cc0'
}
headers['X-User-Id'] = 'primary'
request = requests.post(API_URL + '/company/locations', headers = headers, json = body)
print(request.json())
POST /company/locations
Create a new location, add it to the current company and return it.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| body | body | location object |
true | location to be added to the company |
Responses
| Status | Meaning | Description |
|---|---|---|
| 201 | Created | A location was successfully created and returned. |
| 400 | Bad Request | Provided location information could not be validated. |
| 403 | Forbidden | Requesting user is not the company owner. |
Update company locations
Partially update a company location
location_id = '61254e7ecbe793d0e26c7996'
headers['X-User-Id'] = 'primary'
body = {
'name': 'Old Location'
}
request = requests.patch(API_URL + '/company/locations/' + location_id, \
headers = headers, json = body)
print(request.json())
PATCH /company/locations/{location_id}
Partially update the given location with the provided request body data.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
location_id |
path | location id string |
true | ID of the location to be updated |
| body | body | location object |
true | Partial or full location object |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | location successfully updated and returned. |
| 400 | Bad Request | Some of the provided fields are not valid. |
| 403 | Forbidden | User has no permission to edit this location. |
| 404 | Not Found | location with the given ID does not exist. |
Delete location
Delete a location from the company
location_id = '61254e7ecbe793d0e26c7996'
headers['X-User-Id'] = 'primary'
request = requests.delete(API_URL + '/company/locations/' + location_id, headers = headers)
print(request.json())
DELETE /company/locations/{location_id}
Delete the given location.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
location_id |
path | location id string |
true | ID of the location to be deleted |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | location successfully deleted. |
| 403 | Forbidden | Requesting user is not the company owner. |
| 404 | Not Found | location with the given ID does not exist. |
Instances
instance endpoints
Get instances
Get the list of all instances in the company
request = requests.get(API_URL + '/instances', headers = headers)
print(request.json())
GET /instances
Return the list of PBX instances available to the company.
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | An array of instances successfully returned. |
Extensions
extension endpoints.
Get extensions
Get the third page of an instance's softphone extensions, sorted by user names
instance_uuid = '279951a6-4f51-5019-a897-0e7624828abf'
query = {
'by_user': 'on',
'filter_by': 'softphone',
'page': 3
}
request = requests.get(API_URL + '/instances/' + instance_uuid + '/bulks/extensions', \
headers = headers, params = query)
print(request.json())
GET /instances/{instance_uuid}/bulks/extensions
Return the list of extensions by PBX ID.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
instance_uuid |
path | instance uuid string |
true | UUID of the instance |
filter_by |
query | enum string | false | Query filter |
by_user |
query | enum string | false | Whether to sort by user |
search |
query | string | false | Search query |
page |
query | integer | false | Index of the page of extensions |
page_size |
query | integer | false | Number of extensions per page |
Enumerated Values
| Parameter | Value |
|---|---|
filter_by |
unassigned |
filter_by |
softphone |
by_user |
on |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | An array of extensions successfully returned. |
| 404 | Not Found | extensions by this PBX do not exist or instance by the given ID does not exist. |
Response Headers
| Status | Header | Type | Description |
|---|---|---|---|
| 200 | X-Pagination-Total-Count |
integer | Total number of extensions |
| 200 | X-Pagination-Page-Count |
integer | Number of pages |
| 200 | X-Pagination-Current-Page |
integer | Index of the current page |
| 200 | X-Pagination-Per-Page |
integer | Number of extensions per page |
Add new extensions
Add a new extension to an instance
instance_uuid = '79951a6-4f51-5019-a897-0e7624828abf'
body = {
'data': {
'id': 1123,
'name': 'Test',
'description': null,
'voicemail_email': 'voice@example.com',
'outboundcid': null
},
'location_id': '60190fb650fe88ed1a544a85',
'purpose': 'mobile-app'
}
request = requests.post(API_URL + '/instances/' + instance_uuid + '/bulks/extensions', \
headers = headers, json = body)
print(request.json())
POST /instances/{instance_uuid}/bulks/extensions
Add a new extension to the given PBX instance and the database.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
instance_uuid |
path | instance uuid string |
true | UUID of the instance to add the extension to |
| body | body | extension object |
true | extension to be added |
Responses
| Status | Meaning | Description |
|---|---|---|
| 201 | Created | New extension has been successfully created and returned. |
| 400 | Bad Request | extension provided contains invalid values. |
| 502 | Bad Gateway | FreePBX response with error returned. |
Get all extensions assigned to a user
Get all softphone extensions assigned to a user
contact_id = '60190ce750fe88ed1a544a7a'
query = {
'purpose': 'softphone'
}
request = requests.get(API_URL + '/account/' + contact_id + '/extensions', \
headers = headers, params = query)
print(request.json())
GET /account/{contact_id}/extensions
Get the list of extensions assigned to the given user.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
contact_id |
path | contact id string |
true | ID of the target user |
purpose |
query | enum string | false | Purpose of the extension |
Enumerated Values
| Parameter | Value |
|---|---|
purpose |
softphone |
purpose |
unassigned |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | An array of extensions successfully returned. |
| 404 | Not Found | contact with the given ID does not exist. |
Find extensions
Find the fifth page of unassigned extensions on an instance
instance_uuid = '79951a6-4f51-5019-a897-0e7624828abf'
query = {
'filter_by': 'unassigned',
'page': 5
}
request = requests.get(API_URL + '/instances/' + instance_uuid + '/extensions', \
headers = headers, params = query)
print(request.json())
GET /instances/{instance_uuid}/extensions
Return the list of extensions, optionally filtered and sorted by query parameters.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
instance_uuid |
path | instance uuid string |
true | UUID of the target instance |
filter_by |
query | enum string | false | Type of extension to filter by |
by_user |
query | enum string | false | Whether to filter by user instead |
search |
query | string | false | Search query |
page |
query | integer | false | Current page number |
page_size |
query | integer | false | Size of each page |
Enumerated Values
| Parameter | Value |
|---|---|
filter_by |
unassigned |
filter_by |
softphone |
by_user |
on |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | An array of extensions successfully returned. |
| 404 | Not Found | extensions by this PBX do not exist. |
Check user extension assignments
Check for duplicate extensions on a given user
instance_uuid = '79951a6-4f51-5019-a897-0e7624828abf'
body = {
'email': 'john@example.com',
'id': 1001
}
request = requests.post(API_URL + '/instances/' + instance_uuid + '/bulks/extensions/check', \
headers = headers, json = body)
print(request.json())
POST /instances/{instance_uuid}/bulks/extensions/check
Check possible duplicate assignments for extensions.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
instance_uuid |
path | instance uuid string |
true | UUID of the target instance |
| body | body | object | true | Payload |
» email |
body | string | true | Email address of the user to be assigned |
» id |
body | integer | true | Extension number |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | User has no assignments. |
| 400 | Bad Request | There are existing extension assignments or payload not provided. |
| 404 | Not Found | instance with the given ID does not exist. |
Update extension
Replace an extension
body = new_extension
instance_uuid = '79951a6-4f51-5019-a897-0e7624828abf'
extension_id = '61254e7f884ca03e99ba0dfe'
request = requests.put(API_URL + '/instances/' + instance_uuid + '/bulks/extensions/' + extension_id, \
headers = headers, json = body)
print(request.json())
PUT /instances/{instance_uuid}/bulks/extensions/{extension_id}
Update details for the given extension.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
instance_uuid |
path | instance uuid string |
true | UUID of the instance the extension belongs to |
extension_id |
path | extension id string |
true | ID of the target extension |
| body | body | extension object |
true | Replacement extension |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | extension successfully updated and returned. |
| 400 | Bad Request | extension provided contains invalid values. |
| 404 | Not Found | extension with the given ID or instance with the given ID does not exist. |
| 502 | Bad Gateway | FreePBX response with error returned. |
Delete extension
Delete an extension from a given instance
instance_uuid = '79951a6-4f51-5019-a897-0e7624828abf'
extension_id = '61254e7f884ca03e99ba0dfe'
request = requests.delete(API_URL + '/instances/' + instance_uuid + '/bulks/extensions/' + extension_id, \
headers = headers)
print(request.json())
DELETE /instances/{instance_uuid}/bulks/extensions/{extension_id}
Delete the given extension from the PBX instance and the database.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
instance_uuid |
path | instance uuid string |
true | UUID of the instance the extension belongs to |
extension_id |
path | extension id string |
true | ID of the target extension |
Responses
| Status | Meaning | Description |
|---|---|---|
| 204 | No Content | extension successfully deleted. |
| 404 | Not Found | extension with the given ID or instance with the given UUID does not exist. |
| 502 | Bad Gateway | FreePBX response with error returned. |
Get extension configuration by ID
Get extension configuration
query = {
'instance_uuid': '79951a6-4f51-5019-a897-0e7624828abf',
'extension_id': '61254e7f884ca03e99ba0dfe'
}
request = requests.get(API_URL + '/phones/qr-config/advanced', headers = headers, params = query)
print(request.json())
GET /phones/qr-config/advanced
You can use that configuration to connect extension with any VoIP softphone
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
extension_id |
query | extension id string |
true | ID of the target extension |
instance_uuid |
query | instance uuid string |
true | UUID of the instance the extension belongs to |
Texting - Conversations
conversation endpoints.
Get all conversations
Get conversations
request = requests.get(API_URL + '/texting/conversations, headers = headers)
print(request.json())
GET /texting/conversations
Get all conversations in the company.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
page |
query | integer | false | Index of the page of conversations |
per_page |
query | integer | false | Number of conversations per page |
Response Headers
| Status | Header | Type | Description |
|---|---|---|---|
| 200 | X-Pagination-Total-Count |
integer | Total number of conversations |
| 200 | X-Pagination-Page-Count |
integer | Number of pages |
| 200 | X-Pagination-Current-Page |
integer | Index of the current page |
| 200 | X-Pagination-Per-Page |
integer | Number of conversations per page |
Search conversations
Search for text within conversations
query = {
'text': 'Development Talks'
}
request = requests.get(API_URL + '/texting/conversations/search', headers = headers, params = query)
print(request.json())
GET /texting/conversations/search
Get messages from all conversations in the company by text search.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
text |
query | string | false | Search query |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | An array of conversation objects successfully returned. |
Create new conversations
Create a conversation
body = {
'contact_id': '615717df4b8fa06267cd2f6f',
'from_number': '1235551234'
}
request = requests.post(API_URL + '/texting/conversations', headers = headers, json = body)
print(request.json())
POST /texting/conversations
Create a new conversation.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| body | body | conversation object |
true | conversation to be created |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | A conversation already exists for the provided source and destination numbers. |
| 201 | Created | New conversation was successfully created and returned. |
Delete conversations
Delete a conversation
conversation_id = '616566b94b8fa0626751ef96'
request = requests.delete(API_URL + '/texting/conversations/` + conversation_id, headers = headers)
print(request.json())
DELETE /texting/conversations/{conversation_id}
Delete the given conversation with all the messages in it.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
conversation_id |
path | conversation id string |
true | ID of the target conversation |
Responses
| Status | Meaning | Description |
|---|---|---|
| 204 | No Content | conversation and messages were successfully deleted. |
| 404 | Not Found | conversation with the given ID does not exist. |
Texting - Messages
message endpoints
Get messages from conversation
Fetch the third page of messages from a conversation
conversation_id = '616566b94b8fa0626751ef96'
query = {
'page': 3
}
request = requests.get(API_URL + '/texting/conversations/' + conversation_id + '/messages', \
headers = headers, params = query)
print(request.json())
GET /texting/conversations/{conversation_id}/messages
Get messages from a given conversation.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
page |
query | integer | false | Index of the page of messages |
per_page |
query | integer | false | Number of messages per page |
Response Headers
| Status | Header | Type | Description |
|---|---|---|---|
| 200 | X-Pagination-Total-Count |
integer | Total number of messages |
| 200 | X-Pagination-Page-Count |
integer | Number of pages |
| 200 | X-Pagination-Current-Page |
integer | Index of the current page |
| 200 | X-Pagination-Per-Page |
integer | Number of messages per page |
Mark message as read
Mark a specific message in a conversation as seen
body = {
'is_read': True
}
conversation_id = '615717df4b8fa06267cd2f73'
message_id = '615717dfaea77fef6ace1bbf'
request = requests.patch(API_URL + '/texting/conversations/' + conversation_id + '/messages/' + message_id, \
headers = headers, json = body)
print(request.json())
PATCH /texting/conversations/{conversation_id}/messages/{message_id}
Update a message in a conversation as read.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
message_id |
path | message id string |
true | ID of the message being updated |
conversation_id |
path | conversation id string |
true | ID of the conversation the message belongs to |
| body | body | object | true | Payload |
» is_read |
body | boolean | true | Whether the message should be marked as read |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | message successfully updated and returned. |
| 400 | Bad Request | Payload contains invalid values. |
| 404 | Not Found | A message of the given ID does not exist. |
Send outbound message
Send a message
conversation_id = '615717df4b8fa06267cd2f73'
body = {
'text': 'Hello world!'
}
request = requests.post(API_URL + '/texting/conversations/' + conversation_id + '/messages/publish', \
headers = headers, json = body)
print(request.json())
POST /texting/conversations/{conversation_id}/messages/publish
Send an SMS or MMS message.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
conversation_id |
path | conversation id string |
true | ID of the target conversation |
| body | body | message object |
true | message to be sent |
Responses
| Status | Meaning | Description |
|---|---|---|
| 201 | Created | message was successfully sent. |
Get messages in conversation
Get the ten latest messages in a conversation
query = {
'per_page': 10,
'page': 1
}
conversation_id = '615717df4b8fa06267cd2f73'
request = requests.get(API_URL + '/texting/conversations/' + conversation_id + '/messages', \
headers = headers, params = query)
print(request.json())
GET /texting/conversations/{conversation_id}/messages
Return the list of messages in the given conversation.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
conversation_id |
path | conversation id string |
true | ID of the conversation being queried |
page |
query | integer | false | Index of the page of messages |
per_page |
query | integer | false | Number of messages per page |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | An array of messages in conversation successfully returned. |
| 404 | Not Found | conversation with the given ID does not exist. |
Response Headers
| Status | Header | Type | Description |
|---|---|---|---|
| 200 | X-Pagination-Total-Count |
integer | Total number of messages in conversation |
| 200 | X-Pagination-Page-Count |
integer | Number of pages |
| 200 | X-Pagination-Current-Page |
integer | Index of the current page |
| 200 | X-Pagination-Per-Page |
integer | Number of messages per page |
Delete messages in conversation
Delete two specific messages in a conversation
query = {
'ids': ['61656c90730737f190ed288a', '615717dfaea77fef6ace1bbf']
}
conversation_id = '615717df4b8fa06267cd2f73'
request = requests.delete(API_URL + '/texting/conversations/' + conversation_id + '/messages', \
headers = headers)
print(request.json())
DELETE /texting/conversations/{conversation_id}/messages
Delete multiple messages in given conversation.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
ids |
query | [message id string] |
false | IDs of messages to be deleted |
conversation_id |
path | conversation id string |
true | conversation the messages belong to |
Responses
| Status | Meaning | Description |
|---|---|---|
| 204 | No Content | messages in the conversation were successfully deleted. |
| 404 | Not Found | messages with the given IDs or conversation with the given ID do not exist. |
Texting - Contacts
texting contact endpoints
Create texting contact
Create a new contact for texting
body = {
'number': '+12340009999'
}
request = requests.post(API_URL + '/texting/contacts', headers = headers, json = body)
print(request.json())
POST /texting/contacts
Create a texting contact. A company_id field will be added automatically.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| body | body | texting contact object |
true | texting contact to create |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | Given texting contact already exists for this company. |
| 201 | Created | texting contact successfully created and returned. |
Get texting contacts
Find texting contacts named Jane
query = {
'search': 'Jane'
}
request = requests.get(API_URL + '/texting/contacts', headers = headers, params = query)
print(request.json())
GET /texting/contacts
Return the list of texting contacts.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
search |
query | string | false | Search query |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | An array of texting contacts successfully returned. |
| 404 | Not Found | texting contact with the given ID does not exist. |
Get texting contact by ID
Get a texting contact
texting_contact_id = '61254ea54b8fa062670a3fb1'
request = requests.get(API_URL + '/texting/contacts/' + texting_contact_id, headers = headers)
print(request.json())
GET /texting/contacts/{texting_contact_id}
Get texting contact by ID.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
texting_contact_id |
path | texting contact id string |
true | ID of the texting contact to be returned |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | texting contact successfully returned. |
| 404 | Not Found | texting contact with the given ID does not exist. |
Update texting contact
Replace a texting contact
texting_contact_id = '61254ea54b8fa062670a3fb1'
body = {
'number': '11235554321'
}
request = requests.put(API_URL + '/texting/contacts/' + texting_contact_id, \
headers = headers, json = body)
print(request.json())
PUT /texting/contacts/{texting_contact_id}
Update texting contact. company_id parameter will be added automatically.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
texting_contact_id |
path | texting contact id string |
true | ID of the texting contact to be updated |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | texting contact successfully updated. |
| 404 | Not Found | texting contact with the given ID does not exist. |
Texting - Numbers
texting number endpoints
Get texting numbers
Get available texting numbers
query = {
'numformat': 'international'
}
request = requests.get(API_URL + '/texting/numbers', headers = headers, params = query)
print(request.json())
GET /texting/numbers
Return texting numbers owned by the current user.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
numformat |
query | enum string | false | Telephone number format for the response string. |
Enumerated Values
| Parameter | Value |
|---|---|
numformat |
international |
numformat |
national |
Example response
[
{
"company_id": "611ced1255c44a89f8df7cc0",
"id": "61254e814b8fa062670a3e14",
"number": "+18273717273",
"ownership": [
"janedoe@example.com"
]
}
]
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | An array of texting numbers successfully returned. |
Update number ownership
Assign two email addresses to a texting number
number = '3215551234'
body = ['janedoe@example.com', 'johnsmith@example.com']
request = requests.put(API_URL + '/texting/numbers/' + number, headers = headers, json = body)
print(request.json())
PUT /texting/numbers/{number}
Update the owner emails of the texting number for the given number.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
number |
path | string | true | Number of the texting number to be updated |
| body | body | [string] | true | Array of emails to assign texting number ownership to |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | texting number successfully updated and returned. |
| 404 | Not Found | texting number with the given number does not exist. |
Voicemails
voicemail endpoints
Get voicemails
Get the third page of voicemails from extensions 1001 to 1002
query = {
'extension_source': 1001,
'extension_destination': 1002,
'page': 3
}
request = requests.get(API_URL + '/voicemail/messages/', headers = headers, params = query)
print(request.json())
GET /voicemail/messages
Return the list of all available voicemails, optionally filtered and sorted with query parameters.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
from_date |
query | date string | false | Starting date |
to_date |
query | date string | false | Ending date |
page |
query | integer | false | Index of the page of voicemails |
per_page |
query | integer | false | Number of voicemails per page |
sort |
query | [string] | false | Fields to sort by |
extension_source |
query | integer | false | Number of the sending extension |
extension_destination |
query | integer | false | Number of the receiving extension |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | An array of voicemails successfully returned. |
| 400 | Bad Request | Invalid parameter provided. |
Response Headers
| Status | Header | Type | Description |
|---|---|---|---|
| 200 | X-Pagination-Total-Count |
integer | Total number of voicemails |
| 200 | X-Pagination-Page-Count |
integer | Number of pages |
| 200 | X-Pagination-Current-Page |
integer | Index of the current page |
| 200 | X-Pagination-Per-Page |
integer | Number of voicemails per page |
Fax - Destinations
destination endpoints
Create fax destination
Create new destination
body = {'emails': ['myfax@example.com']}
request = requests.post(API_URL + '/fax/destinations', headers = headers, json = body)
print(request.json())
POST /fax/destinations
Create a new destination for fax messages.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| body | body | destination object |
true | destination to create |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | Given destination already exists for this company. |
| 201 | Created | destination successfully created and returned. |
Fax - Messages
fax message endpoints
Get inbound fax messages
Get messages from a specific sender with a specific subject between certain dates
query = {
'name': 'Alyssa',
'subject': 'Payment Details',
'start_date': '2021-11-01T18:00:00',
'end_date': '2021-06-01T09:00:00'
}
request = requests.get(API_URL + '/fax/messages/inbound', headers = headers, params = query)
print(request.json())
GET /fax/messages/inbound
Return the list of inbound fax messages, optionally filtered and sorted by paremeters.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
page |
query | integer | false | Index of the page of fax messages |
per_page |
query | integer | false | Number of fax messages per page |
sort |
query | [string] | false | Fields to sort by |
start_date |
query | date string | false | Starting date |
end_date |
query | date string | false | Ending date |
number |
query | string | false | Source fax number |
name |
query | string | false | Sender name |
is_read |
query | boolean | false | Read status |
undefined |
query | boolean | false | Whether to show messages from anonymous/undefined senders |
subject |
query | string | false | Message subject |
search |
query | string | false | Search string |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | An array of fax messages successfully returned. |
| 400 | Bad Request | Invalid parameter provided. |
Response Headers
| Status | Header | Type | Description |
|---|---|---|---|
| 200 | X-Pagination-Total-Count |
integer | Total number of fax messages |
| 200 | X-Pagination-Page-Count |
integer | Number of pages |
| 200 | X-Pagination-Current-Page |
integer | Index of the current page |
| 200 | X-Pagination-Per-Page |
integer | Number of fax messages per page |
Delete an inbound fax message
Delete an inbound message
fax_message_id = 'a8f3260b07657b92121973fc'
request = requests.delete(API_URL + '/fax/messages/inbound/' + fax_message_id, headers = headers)
print(request.json())
DELETE /fax/messages/inbound/{fax_message_id}
Delete the given fax message.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
fax_message_id |
path | fax message id string |
true | ID of the fax message to be deleted |
Responses
| Status | Meaning | Description |
|---|---|---|
| 204 | No Content | fax message successfully deleted. |
| 404 | Not Found | fax message with the given ID does not exist. |
Update an inbound fax message
Partially update an inbound fax message
body = {
'to_name': 'Alice'
}
fax_message_id = 'a8f3260b07657b92121973fc'
request = requests.patch(API_URL + '/fax/messages/inbound/' + fax_message_id, \
headers = headers, json = body)
print(request.json())
PATCH /fax/messages/inbound/{fax_message_id}
Partially update the given inbound fax message.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
fax_message_id |
path | fax message id string |
true | ID of the fax message to be updated |
| body | body | fax message object |
true | Partial or full fax message object |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | fax message successfully updated and returned. |
| 400 | Bad Request | Payload contains invalid values. |
| 404 | Not Found | fax message with the given ID does not exist. |
Get outbound fax messages
Get messages to a specific recipient with a specific subject between certain dates
query = {
'name': 'Bob',
'subject': 'Status Update',
'start_date': '2021-11-01T18:00:00',
'end_date': '2021-06-01T09:00:00'
}
request = requests.get(API_URL + '/fax/messages/outbound', headers = headers, params = query)
print(request.json())
GET /fax/messages/outbound
Return the list of outbound fax messages, optionally filtered and sorted by paremeters.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
page |
query | integer | false | Index of the page of fax messages |
per_page |
query | integer | false | Number of fax messages per page |
sort |
query | [string] | false | Fields to sort by |
start_date |
query | date string | false | Starting date |
end_date |
query | date string | false | Ending date |
number |
query | string | false | Destination fax number |
name |
query | string | false | Recipient name |
subject |
query | string | false | Message subject |
search |
query | string | false | Search string |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | An array of fax messages successfully returned. |
| 400 | Bad Request | Invalid parameter provided. |
Response Headers
| Status | Header | Type | Description |
|---|---|---|---|
| 200 | X-Pagination-Total-Count |
integer | Total number of fax messages |
| 200 | X-Pagination-Page-Count |
integer | Number of pages |
| 200 | X-Pagination-Current-Page |
integer | Index of the current page |
| 200 | X-Pagination-Per-Page |
integer | Number of fax messages per page |
Send a new fax message
Create an outbound message
body = {
'emails': 'bob@example.com',
'file': {'id': '30b19a2ff4cb9e50ac109eae'},
'from': '2052726012',
'from_name': 'Alice',
'subject': 'Update my contact details',
'to': '8584375000',
'to_name': 'Bob'
}
request = requests.post(API_URL + '/fax/messages/outbound', headers = headers, json = body)
print(request.json())
POST /fax/messages/outbound
Create a new outbound fax message and send it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| body | body | fax message object |
fax message to be created and sent |
Responses
| Status | Meaning | Description |
|---|---|---|
| 201 | Created | fax message successfully created and sent. |
| 400 | Bad Request | Payload contains invalid values. |
Delete an outbound fax message locally
Delete an outbound message
fax_message_id = 'a8f3260b07657b92121973fc'
request = requests.delete(API_URL + '/fax/messages/outbound/' + fax_message_id, headers = headers)
print(request.json())
DELETE /fax/messages/outbound/{fax_message_id}
Delete the local data for the given outbound fax message.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
fax_message_id |
path | fax message id string |
ID of the fax message to be deleted |
Responses
| Status | Meaning | Description |
|---|---|---|
| 204 | No Content | fax message successfully deleted. |
| 404 | Not Found | fax message with the given ID does not exist. |
Update a failed fax message
Update an outbound message before it is resent
body = {
'to': '8584375001'
}
fax_message_id = 'a8f3260b07657b92121973fc'
request = requests.put(API_URL + '/fax/messages/outbound/' + fax_message_id, \
headers = headers, json = body)
print(request.json())
PUT /fax/messages/outbound/{fax_message_id}
Update an outbound fax message that has failed.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
fax_message_id |
path | fax message id string |
ID of the fax message to be updated |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | fax message successfully updated and returned. |
| 400 | Bad Request | Payload contains invalid values. |
| 404 | Not Found | fax message with the given ID does not exist. |
| 406 | Not Acceptable | This operation is only available for failed outbound fax messages. |
Retry a failed fax message
Resend outbound message
fax_message_id = 'a8f3260b07657b92121973fc'
request = requests.post(API_URL + '/fax/messages/outbound/' + fax_message_id + '/retry', \
headers = headers)
print(request.json())
POST /fax/messages/outbound/{fax_message_id}/retry
Resend an outbound fax message that has failed.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
fax_message_id |
path | fax message id string |
ID of the fax message to be resent |
Responses
| Status | Meaning | Description |
|---|---|---|
| 202 | Accepted | fax message accepted for resending and returned. |
| 404 | Not Found | fax message with the given ID does not exist. |
| 406 | Not Acceptable | This operation is only available for failed outbound fax messages. |
Get scheduled fax messages
Get scheduled messages to a specific number created before a certain date
query = {
'number': '3215551234',
'end_date': '2021-06-01T09:00:00'
}
request = requests.get(API_URL + '/fax/messages/scheduled', headers = headers, params = query)
print(request.json())
GET /fax/messages/scheduled
Return the list of fax messages scheduled for sending, optionally filtered and sorted by paremeters.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
page |
query | integer | false | Index of the page of fax messages |
per_page |
query | integer | false | Number of fax messages per page |
sort |
query | [string] | false | Fields to sort by |
start_date |
query | date string | false | Starting date |
end_date |
query | date string | false | Ending date |
number |
query | string | false | Destination fax number |
name |
query | string | false | Recipient name |
subject |
query | string | false | Message subject |
search |
query | string | false | Search string |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | An array of fax messages successfully returned. |
| 400 | Bad Request | Invalid parameter provided. |
Response Headers
| Status | Header | Type | Description |
|---|---|---|---|
| 200 | X-Pagination-Total-Count |
integer | Total number of fax messages |
| 200 | X-Pagination-Page-Count |
integer | Number of pages |
| 200 | X-Pagination-Current-Page |
integer | Index of the current page |
| 200 | X-Pagination-Per-Page |
integer | Number of fax messages per page |
Schedule a new fax message
Create new message to be sent at a given date
body = {
'emails': 'bob@example.com',
'file': {'id': '30b19a2ff4cb9e50ac109eae'},
'from': '2052726012',
'from_name': 'Alice',
'subject': 'Remember to update my contact details',
'to': '8584375000',
'to_name': 'Bob',
'send_at': '2021-11-15T09:00:00' # Time of schedule
}
request = requests.post(API_URL + '/fax/messages/scheduled', headers = headers, json = body)
print(request.json())
POST /fax/messages/scheduled
Create a new outbound fax message and schedule it for sending.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| body | body | fax message object |
fax message to be created and scheduled |
Responses
| Status | Meaning | Description |
|---|---|---|
| 201 | Created | fax message successfully created and scheduled. |
| 400 | Bad Request | Payload contains invalid values. |
Cancel a scheduled fax message
Delete a scheduled message
fax_message_id = '7081e68fcebe251d6b612fb2'
request = requests.delete(API_URL + '/fax/messages/scheduled/' + fax_message_id, headers = headers)
print(request.json())
DELETE /fax/messages/scheduled/{fax_message_id}
Delete a scheduled fax message before it could be sent.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
fax_message_id |
path | fax message id string |
ID of the fax message to be deleted |
Responses
| Status | Meaning | Description |
|---|---|---|
| 204 | No Content | fax message successfully deleted. |
| 404 | Not Found | fax message with the given ID does not exist. |
Update a scheduled fax message
Update a message before it can be sent
body = {
'subject': 'Update my contact details (important!)'
}
fax_message_id = 'a8f3260b07657b92121973fc'
request = requests.put(API_URL + '/fax/messages/scheduled/' + fax_message_id, \
headers = headers, json = body)
print(request.json())
PUT /fax/messages/scheduled/{fax_message_id}
Update a scheduled fax message.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
fax_message_id |
path | fax message id string |
ID of the fax message to be updated |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | fax message successfully updated and returned. |
| 400 | Bad Request | Payload contains invalid values. |
| 404 | Not Found | fax message with the given ID does not exist. |
Get fax statistics
Get fax message statistics for the company
request = requests.get(API_URL + '/fax/statistics', headers = headers)
print(request.json())
GET /fax/statistics
Return the numbers of total fax messages in the company.
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | An object of fax message numbers successfully returned. |
On 200 OK:
| Field | Type | Description | Example |
|---|---|---|---|
inbound |
integer | Number of inbound messages | 10 |
inbound_hidden |
integer | Number of hidden inbound messages | 3 |
outbound |
integer | Number of outbound messages | 5 |
Fax - Numbers
Get fax numbers
Get all fax numbers
request = requests.get(API_URL + '/fax/numbers', headers = headers)
print(request.json())
GET /fax/numbers
Return the list of all fax numbers available in the company.
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | An array of fax number strings successfully returned. |
Meet - Authentication
Get calendar for current user
Get calendar
request = requests.get(API_URL + '/meet/app/calendar', headers = headers)
print(request.json())
GET /meet/app/calendar
Return the Google Calendar details for the current contact.
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | Calendar description object successfully returned. |
| 404 | Not Found | There is no calendar for this contact. |
On 200 OK:
| Field | Type | Description | Example |
|---|---|---|---|
calendar |
string | Calendar link | |
update |
date string | Date of last update | "2021-12-12" |
user_id |
contact id string |
ID of the contact |
"60190ce750fe88ed1a544a7a" |
Get meeting link
Get URL for specified meeting
meeting_id = '214824405'
request = requests.get(API_URL + '/meet/app/calendar/events/get-link/' + meeting_id, \
headers = headers)
print(request.json())
GET /meet/app/calendar/events/get-link/{meeting_id}
Return a meeting URL object for the given meeting ID.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
meeting_id |
path | id string | ID of the meeting |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | Meeting link object successfully returned. |
| 404 | Not Found | Invalid meeting ID. |
On 200 OK:
| Field | Type | Description | Example |
|---|---|---|---|
full_link |
string | URL of the meeting | "https://meet.ringplan.com/..." |
Get Google Calendar authentication link
Get Google Calendar OAuth2 link
request = requests.get(API_URL + '/meet/app/calendar/get-auth-url', headers = headers)
print(request.json())
GET /meet/app/calendar/get-auth-url
Return the Google Calendar OAuth2 authentication URL object for the current contact.
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | OAuth2 URL successfully returned. |
On 200 OK:
| Field | Type | Description | Example |
|---|---|---|---|
auth_url |
string | Google Calendar OAuth2 URL | "https://accounts.google.com/o/oauth2/auth?..." |
Get Outlook Calendar authentication link
Get Outlook Calendar OAuth2 link
request = requests.get(API_URL + '/meet/app/outlook/get-auth-url', headers = headers)
print(request.json())
GET /meet/app/outlook/get-auth-url
Return the Outlook Calendar OAuth2 authentication URL object for the current contact.
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | OAuth2 URL successfully returned. |
On 200 OK:
| Field | Type | Description | Example |
|---|---|---|---|
auth_url |
string | Outlook Calendar OAuth2 URL | "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?..." |
Revoke Google Calendar authentication
Revoke Google Calendar authentication
body = {
'calendar': 'example@gmail.com'
}
request = requests.post(API_URL + '/meet/google/revoke, headers = headers, json = body)
print(request.json())
POST /meet/google/revoke
Revoke Google Calendar OAuth2 authentication for the current contact.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| body | body | object | true | Payload |
» calendar |
body | string | true | Gmail address |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | Authentication successfully revoked. |
| 400 | Bad Request | Failed to revoke authentication. |
On 200 OK or 400 Bad Request:
| Field | Type | Description | Example |
|---|---|---|---|
result |
boolean | Result | true |
Revoke Outlook Calendar authentication
Revoke Outlook Calendar authentication
body = {
'calendar': 'example@outlook.com'
}
request = requests.post(API_URL + '/meet/outlook/revoke, headers = headers, json = body)
print(request.json())
POST /meet/outlook/revoke
Revoke Outlook Calendar OAuth2 authentication for the current contact.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| body | body | object | true | Payload |
» calendar |
body | string | true | Outlook address |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | Authentication successfully revoked. |
| 400 | Bad Request | Failed to revoke authentication. |
On 200 OK or 400 Bad Request:
| Field | Type | Description | Example |
|---|---|---|---|
result |
boolean | Result | true |
Meet - Events
Webhooks
webhook url and webhook event endpoints
Get webhook callback URL
Get webhook callback URL
request = requests.get(API_URL + '/webhooks/callbacks/url', headers = headers)
print(request.json())
GET /webhooks/callbacks/url
Return the webhook url for the current company.
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | webhook url successfully returned. |
Update webhook callback URL
Update callback URL of a webhook
body = {
'url': 'https://www.example.com'
}
request = requests.put(API_URL + '/webhooks/callbacks/url', headers = headers, json = body)
print(request.json())
PUT /webhooks/callbacks/url
Update the webhook urls for the current company.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| body | body | webhook url object |
true | The webhook url object to update the current one with |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | webhook url successfully updated and returned. |
Get subscribed webhook events
Get webhook callback events
request = requests.get(API_URL + '/webhooks/callbacks', headers = headers)
print(request.json())
GET /webhooks/callbacks
Get the subscribed webhook events.
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | An array of webhook events successfully returned. |
Subscribe to webhook event
Subscribe to a webhook event
body = {
'type': 'texting.message.inbound'
}
request = requests.post(API_URL + '/webhooks/callbacks', headers = headers, json = body)
print(request.json())
POST /webhooks/callbacks
Subscribe to a webhook event.
The event type is one of
dial.action.starteddial.action.completedcall.action.hanguptexting.message.inbound
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| body | body | webhook event object |
true | Replacement webhook event |
Responses
| Status | Meaning | Description |
|---|---|---|
| 201 | Created | A webhook event was successfully created and returned. |
Unsubscribe from webhook event
Delete a subscribed webhook event
webhook_event_id = '6165732029a740a320e8031f'
request = requests.delete(API_URL + '/webhooks/callbacks/' + webhook_event_id, headers = headers)
print(request.json())
DELETE /webhooks/callbacks/{webhook_event_id}
Unsubscribe from webhook event.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook_event_id |
path | webhook event id string |
true | webhook event to unsubscribe from |
Responses
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | Successfully unsubscribed from webhook event. |
WebSocket
RingPlan websocket API works through the same URI as the one used for HTTP requests and is available on every environment. The details are generally uniform with the HTTP API unless noted otherwise.
Socket initialization in JavaScript
import { io } from 'socket.io-client';
const socket = io('https://ssp-backend.ringplan.com', {
path: '/ws',
transports: ['websocket'],
secure: true,
autoConnect: false,
reconnectionDelay: 1500
});
Socket initialization in Python
import socketio
if __name__ == '__main__':
sio.connect('http://ssp-backend.ringplan.com', socketio_path='/ws/')
sio.wait()
The server will emit three types of events:
| Server event | Description |
|---|---|
connect |
Connection successful. |
authenticated |
Authentication successful. |
unauthorized |
Client attempted to send data without authenticating. |
Custom handler
if __name__ == '__main__':
# It is possible to override `trigger_event()` and write a custom handler.
class MyCustomNamespace(socketio.ClientNamespace):
# To catch all events:
def trigger_event(self, event_name, sid, *args):
print(f"{event_name=}, {sid=}")
if args:
print(f"data is {args[0]}")
sio.register_namespace(MyCustomNamespace())
sio.connect('http://ssp-backend.ringplan.com', socketio_path='/ws/')
sio.wait()
In turn, the client can emit the following event:
| Client event | Description |
|---|---|
authenticate |
Sending authentication token. |
After initializing the socket, the client should listen for the connect event,
then reply with an authenticate event containing the authentication token.
Socket authentication in JavaScript
socket.connect()
socket.once('connect', function(socket) {
socket.emit('authenticate', { token: API_KEY });
socket.once('authenticated', function(socket) {
console.log('Authentication successful.');
});
Socket authentication and event handling in Python
@sio.event
def connect():
sio.emit('authenticate', {'token': API_KEY, 'user_email': USER_EMAIL})
print('Connected.')
@sio.event
def disconnect():
print('Disconnected.')
@sio.on('authenticated')
def authenticated(data):
print('Authentication successful.')
@sio.on('unauthorized')
def unauthorized(data):
print('Unauthorized!')
The socket is ready to use once the client receives the authenticated event.
Messages - Client
Message events the client emits to the server and the other clients.
Mark messages as read
texting.message.markAsRead
Mark the given messages as read.
| Name | Type | Description |
|---|---|---|
conversation_id |
conversation id string |
ID of the conversation the messages belong to |
messagesIds |
[message id string] |
Array of IDs of messages to be marked as read |
Messages - Server
Message events the server emits to the clients.
New message
texting.message.new
A new message has arrived.
The server will yield a message object.
Message deletion
texting.message.delete
A message has been deleted.
| Name | Type | Description |
|---|---|---|
id |
message id string |
ID of the deleted message |
conversation_id |
conversation id string |
ID of the conversation |
Message marked read
texting.message.markAsRead
The messages have been marked as read.
| Name | Type | Description |
|---|---|---|
conversation_id |
conversation id string |
ID of the conversation the messages belong to |
messagesIds |
[message id string] |
Array of IDs of messages marked as read |
timezone |
string | Timezone of the sender |
Chats - Server
Chat events the server emits to the clients.
Chat creation
Handle new message
@sio.on('texting.message.new')
def msg_new(data):
print('texting.message.new', data)
texting.chat.new
A new conversation has been created.
The server will yield a conversation object.
Chat deletion
Handle message deletion
@sio.on('texting.message.delete')
def msg_delete(data):
print('texting.message.delete', data)
texting.chat.delete
The conversation has been deleted.
| Name | Type | Description |
|---|---|---|
id |
conversation id string |
ID of the deleted conversation |
User status - Server
user_status_updated
A texting contact's status has changed.
| Name | Type | Description |
|---|---|---|
company_id |
company id string |
ID of the texting contact's company |
user_id |
texting contact id string |
ID of the texting contact |
user_email |
string | Email address |
status |
object | - |
» status |
string | Actual status string |
» action_type |
string | Method the status was set |
id |
id string | Status ID |
created_at |
date string | Date the status was set |
updated_at |
date string | Date the status was updated |
deleted_at |
date string | Date the status was unset |
Objects
RingPlan API uses multiple different objects for internal representation.
Descriptions of object fields are provided below in alphabetical order, following the ID field.
Address
Address has fields that describe individual parts of a company or a user's physical address. Address objects do not have ID fields because they are user provided and are not necessarily unique.
| Field | Type | Description | Example |
|---|---|---|---|
address2 |
string | Secondary address line | |
city |
string | City of residence | "San Diego" |
country |
string | Country of residence | "United States" |
number |
string | Building number | |
state |
string | State code (if applicable) | "CA" |
street |
object | Street details | - |
» name |
string | Street name | "Foo Lane" |
» number |
integer | Street number | 23 |
» type |
string | Street type | "Avenue" |
zip |
string | US ZIP code (if applicable) | "12345" |
Company
Company holds the information for each individual company. The company object forms the core of the object relations in RingPlan API.
| Field | Type | Description | Example |
|---|---|---|---|
id |
company id string |
Internal ID | "611ced1255c44a89f8df7cc0" |
address |
address object |
Physical address | see Address |
affiliate |
boolean | Participating in partner invite program | false |
billing_email |
string | Email address for invoices | "billing@example.com" |
created |
date string | Date of account creation | "2021-08-18T14:20:50.837000+0100" |
description |
string | Additional information | |
email |
string | Email address | "contact@example.com" |
emergency_contact_number |
string | Emergency contact number | "15554441234" |
employees |
integer | Number of users | 5 |
fax |
string | Fax number | "13235551234" |
name |
string | Formal name | "Example Corp" |
onboarding |
boolean | Onboarding successfully completed | true |
partner_id |
id string | Partner invite program ID | |
phone |
string | Regular contact number | "15555554321" |
revenue |
integer | Recognised revenue | |
status |
string | Current status | "active" |
updated |
date string | Date of last update | "2021-08-25T02:53:44.016000+0100" |
website |
string | Homepage URL | "https://example.com" |
Contact
Contact describes a user within a company. Each user belongs to a company.
| Field | Type | Description | Example |
|---|---|---|---|
id |
contact id string |
Internal ID | "611ced1355c44a89f8df7cc3" |
activated |
boolean | Whether the user is enabled | true |
address |
address object |
Physical address of the user | see Address |
birthdate |
date string | Date of birth | |
company_id |
company id string |
ID of the company the user belongs to | "611ced1255c44a89f8df7cc0" |
contacts |
object | Contact numbers and addresses | - |
» email |
string | Email address | "janedoe@example.com" |
» fax |
string | Fax number | |
» phones |
object | Phone numbers | - |
» » home |
string | Home number | |
» » mobile |
string | Mobile number | |
» » other |
string | Miscellaneous numbers | |
» » work |
string | Work number | |
created |
date string | Account creation date | "2021-08-18T11:20:51.510000Z" |
description |
string | Additional information | |
extension |
object | Extension number | - |
» id |
id string | Internal ID | "61254e7f884ca03e99ba0dfe" |
» description |
string | Information about extension |
"Megacorp Accountancy Department" |
» name |
string | Name of the extension |
"MC Acc Dpt" |
» number |
integer | extension number |
1001 |
first_name |
string | Forename | "Jane" |
invitation |
object | User creation invitation information | - |
» accepted_at |
date string | Invitation link acceptance date | |
» expired_at |
date string | Invitation link expiry date | |
» issued_at |
date string | Invitation link creation date | |
» status |
string | Invitation link status | "accepted" |
last_enter |
date string | Date of last login | "2021-08-24T19:46:12Z" |
last_name |
string | Surname | "Doe" |
primary_agent |
contact id string |
Primary agent ID if user is in an agent group | |
timezone |
string | Preferred timezone | "UTC" |
title |
string | Honorary title | "Ms" |
updated |
date string | Date of last update | "2021-08-25T00:05:44.201000Z", |
Conversation
Conversation represents the communication between a texting contact and phone numbers. Each conversation contains messages.
| Field | Type | Description | Example |
|---|---|---|---|
id |
conversation id string |
Internal ID | "615717df4b8fa06267cd2f73" |
company_id |
company id string |
company ID |
"611ced1255c44a89f8df7cc0" |
contact_id |
texting contact id string |
texting contact ID |
"615717df4b8fa06267cd2f6f" |
contactinfo |
texting contact object |
texting contact details |
see Texting Contact |
contactsinfo |
[texting contact object] |
All texting contacts in the conversation |
see Texting Contact |
conversation_type |
string | Type of the conversation |
"direct" |
countunreadmessages |
integer | Number of unread messages in the conversation |
1 |
from_number |
string | Source number | "9513360234" |
has_direct_msg |
boolean | Is the message direct? |
true |
has_hidden_msg |
boolean | Is the message hidden? |
false |
last_message_created_at |
date string | Date of last message's creation |
"2021-10-01T17:14:55.591000+0300" |
lastmessage |
message object |
Last message sent |
|
recipients |
[texting contact id string] |
List of recipient texting contacts |
"615717df4b8fa06267cd2f6f" |
timezone |
string | Timezone of the sender | "Europe/Kiev" |
unread_msg_count |
integer | Same as countunreadmessages |
1 |
updated_at |
date string | Date of last update | "2022-08-10T12:31:37.164696" |
Destination
Destination represents the end-point for a fax message.
| Field | Type | Description | Example |
|---|---|---|---|
id |
destination id string |
Internal ID | "3a677c59dbaca83454fe1db4" |
company |
company id string |
company ID |
"17472b4c9e4fb15f01977c32" |
emails |
[string] | Email addresses | ["user1@company.org","user2@company.org"] |
reprname |
string | Email addresses' representation | "user1@company.org, user2@company.org" |
Extension
Extension represents the internal phone number extensions within a location.
| Field | Type | Description | Example |
|---|---|---|---|
_id |
string | Internal ID | "61254e7f884ca03e99ba0dfe" |
data |
object | - | |
» id |
id integer | 1001 |
|
» accountcode |
string | ||
» allow |
string | ||
» answermode |
string | "disabled" |
|
» avpf |
string | "no" |
|
» bundle |
string | "no" |
|
» busy_cid |
string | ||
» busy_dest |
string | ||
» callerid |
string | "John Smith <1001>" |
|
» callwaiting_enable |
string | "ENABLED" |
|
» chanunavail_cid |
string | ||
» chanunavail_dest |
string | ||
» cid_masquerade |
string | "1001" |
|
» concurrency_limit |
integer | 3 |
|
» context |
string | "from-internal" |
|
» description |
string | "John Smith 1001" |
|
» device_state_busy_at |
string | "0" |
|
» devicetype |
string | "fixed" |
|
» dial |
string | "PJSIP/1001" |
|
» disable_star_voicemail |
string | "no" |
|
» disallow |
string | ||
» dtmfmode |
string | "rfc4733" |
|
» emergency_cid |
string | ||
» extension |
integer | 1001 |
|
» findmefollow_annmsg_id |
string | "0" |
|
» findmefollow_calendar_id |
string | ||
» findmefollow_calendar_match |
string | "yes" |
|
» findmefollow_changecid |
string | "default" |
|
» findmefollow_dring |
|||
» findmefollow_enabled |
string | ||
» findmefollow_fixedcid |
string | ||
» findmefollow_grplist |
string | "1001" |
|
» findmefollow_grppre |
|||
» findmefollow_grptime |
integer | 30 |
|
» findmefollow_needsconf |
False |
||
» findmefollow_postdest |
string | "ext-local,vmu1001,1" |
|
» findmefollow_pre_ring |
integer | 20 |
|
» findmefollow_remotealert_id |
string | "0" |
|
» findmefollow_ringing |
|||
» findmefollow_strategy |
string | "ringallv2" |
|
» findmefollow_toolate_id |
string | "0" |
|
» findmefollow_voicemail |
string | "default" |
|
» force_rport |
string | "yes" |
|
» icesupport |
string | "no" |
|
» intercom |
string | "enabled" |
|
» mailbox |
string | "1001@device" |
|
» max_contacts |
string | "30" |
|
» maximum_expiration |
string | "7200" |
|
» media_encryption |
string | "no" |
|
» media_encryption_optimistic |
string | "no" |
|
» media_use_received_transport |
string | "no" |
|
» mohclass |
string | "default" |
|
» mwi_subscription |
string | "auto" |
|
» name |
string | "John Smith" |
|
» namedcallgroup |
string | ||
» namedpickupgroup |
string | ||
» noanswer |
string | ||
» noanswer_cid |
string | ||
» noanswer_dest |
string | ||
» outboundcid |
string | "\\"MyCorp J. Smith\\" <9513331234>" |
|
» password |
string | ||
» qualifyfreq |
string | "60" |
|
» recording |
string | ||
» recording_in_external |
string | "dontcare" |
|
» recording_in_internal |
string | "dontcare" |
|
» recording_ondemand |
string | "disabled" |
|
» recording_out_external |
string | "dontcare" |
|
» recording_out_internal |
string | "dontcare" |
|
» recording_priority |
integer | 10 |
|
» rewrite_contact |
string | "yes" |
|
» ringtimer |
string | "0" |
|
» rtcp_mux |
string | "no" |
|
» rtp_symmetric |
string | "yes" |
|
» secret |
string | ||
» sendrpid |
string | "pai" |
|
» sipdriver |
string | "chan_pjsip" |
|
» sipname |
string | ||
» tech |
string | "pjsip" |
|
» timers |
string | "yes" |
|
» transport |
string | ||
» trustrpid |
string | "yes" |
|
» user |
string | "1001" |
|
» vmx_busy_enabled |
string | "blocked" |
|
» vmx_option_0_number |
string | ||
» vmx_option_1_number |
string | ||
» vmx_option_2_number |
string | ||
» vmx_play_instructions |
boolean | False |
|
» vmx_temp_enabled |
string | "blocked" |
|
» vmx_unavail_enabled |
string | "blocked" |
|
» voicemail |
string | "default" |
|
» voicemail_email |
string | "jsmith@example.com" |
|
» voicemail_enable |
string | "yes" |
|
» voicemail_options |
string | `"attach=yes\ | |
» voicemail_pager |
string | ||
» voicemail_same_exten |
string | "no" |
|
» voicemail_vmpwd |
string | "1001" |
|
location_id |
location id string |
"61254e7ecbe793d0e26c7996" |
|
outbound_callerid |
object | - | |
» name |
string | "MyCorp J. Smith" |
|
» number |
string | "9513360234" |
|
» value |
string | "\"MyCorp J. Smith\" <9513360234>" |
|
pbx |
instance uuid string |
"279951a6-4f51-5019-a897-0e7624828abf" |
|
phone |
[object] | - | |
» _id |
id string | "61254e804b8fa062670a3df9" |
|
» company |
string | "611ced1255c44a89f8df7cc0" |
|
» data |
object | - | |
» » reg |
[object] | - | |
» » » displayname |
string | "John Smith" |
|
» » » label |
string | "1001" |
|
» » » password |
string | ||
» » » server |
[object] | - | |
» » » » address |
string | "foobar.ringplan.com" |
|
» » » userid |
id integer | 1001 |
|
» extensions |
[extension object] |
see Extension | |
purpose |
string | "ip-phone" |
|
reserved |
object | - | |
» config_id |
id string | "61254e804b8fa062670a3df9" |
|
» to |
string | "polycom" |
|
subscriber |
object | - | |
» call_status |
string | "on_hold" |
|
» extension_id |
extension id string |
"61254e7f884ca03e99ba0dfe" |
|
» state |
string | "UNAUTHENTICATED" |
|
user |
contact object |
see Contact |
Fax Message
A fax message is a message sent through destinations.
| Field | Type | Description | Example |
|---|---|---|---|
id |
fax message id string |
Internal ID | "a8f3260b07657b92121973fc"" |
company |
company id string |
company ID |
"7081e68fcebe251d6b612fb2"" |
created_at |
date string | Date of transmission | "2019-06-13T14:46:24.834000Z"" |
file |
object | Fax contents | - |
» id |
id string | Internal ID | "30b19a2ff4cb9e50ac109eae" |
» internal_id |
id integer | Internal ID | 42 |
from |
string | Source fax number | "2052726012" |
from_name |
string | Sender name | "Bob" |
is_read |
boolean | Whether the message was read | true |
pages |
integer | Length of message in pages | 2 |
subject |
string | Title of the message | "Test FAX message" |
to |
string | Destination fax number | "8584375000" |
to_name |
string | Recipient name | "Alice" |
File
Files are uploaded files used in attachments to messages.
| Field | Type | Description | Example |
|---|---|---|---|
id |
file id string |
Internal ID | "f4f2fdda269d44bc403de84a" |
company_id |
company id string |
company ID |
"5cd2d3384368b16e31c454ff" |
description |
string | Textual description | "A cat on table" |
mimetype |
string | MIME type | "image/jpeg" |
name |
string | Name given | "My Cat" |
preview |
object | Preview | - |
» base64 |
string | Entire preview file in base64 | "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASA...BDAAK3ALon//Z" |
» filename |
string | Preview filename | "cat_picture_preview.jpg" |
» mimetype |
string | MIME type of preview | "image/jpeg" |
size |
integer | Size in bytes | 284821 |
uploaded_at |
date string | Date of upload | "2018-12-29T11:24:22.943306Z" |
uploaded_name |
string | Filename | "cat_picture.jpg" |
user_id |
texting contact id |
Uploading texting contact |
"5cd2d338436ff8b16e31c454" |
Instance
Instance refers to a dedicated PBX instance belonging to a company. The PBX UUID rather than the internal ID is used when referring to instances.
| Field | Type | Description | Example |
|---|---|---|---|
_id |
instance id string |
Internal ID | "61254e7c4b8fa062670a3d9b" |
uuid |
instance uuid string |
PBX UUID | "279951a6-4f51-5019-a897-0e7624828abf" |
accountcode |
string | Internal PBX code for CDR | "SB-A00001234" |
channel_driver |
string | SIP driver | "chan_pjsip" |
company_id |
company id string |
ID of the company |
"611ced1255c44a89f8df7cc0" |
company_name |
string | Name of the company |
"My Company Inc" |
external_domain |
string | Main domain name | "testing.example.com" |
fqdn |
string | Domain name to access the instance |
"foobar.testing.example.com" |
hostname |
string | Internal hostname | "foobar" |
internal_domain |
string | Internal domain | "foobar.local" |
ip |
string | IP address of the host | "198.51.100.1" |
proxy_ip |
string | SIP proxy IP address | "203.0.113.1" |
Location
Location refers to a specific physical location with its own PBX instance. Every company has at least one location.
| Field | Type | Description | Example |
|---|---|---|---|
id |
location id string |
Internal ID | "61254e7ecbe793d0e26c7996" |
address2 |
string | Second line of address | |
building |
object | Building details | - |
» type |
string | Building type | "Apartment" |
» value |
string | Building number | "42" |
callerid |
string | Caller ID service number | "9513360234" |
city |
string | City of location |
"Chula Vista" |
company_id |
company id string |
ID of the company residing |
"611ced1255c44a89f8df7cc0" |
country |
string | Country of location |
"United States" |
e911_provisioned |
boolean | Registered to E911 services? | false |
email |
string | Email address representing the location |
"cv@example.com" |
fax |
string | Fax number | "15554443333" |
latitude |
float | Geographic coordinates | 33.3877219 |
longitude |
float | Geographic coordinates | -116.7919419 |
name |
string | Human readable name of the location |
"Main location" |
pbx_id |
instance uuid string |
UUID of the PBX instance |
"279951a6-4f51-5019-a897-0e7624828abf" |
phone |
string | Main phone number | "15553334444" |
state |
string | First-level administrative division | "CA" |
street |
object | Street details | - |
» name |
string | Street name | "Foo Lane" |
» number |
integer | Street number | 23 |
» type |
string | Street type | "Avenue" |
zip |
string | ZIP code or postal code | "91901" |
Message
A message refers to each text message sent in a conversation.
| Field | Type | Description | Example |
|---|---|---|---|
id |
message id string |
Internal ID | "615717dfaea77fef6ace1bbf" |
campaign_info |
object | Campaign group conversation information | - |
» name |
string | Campaign group conversation event | "NewCampaignCreate" |
conversation_id |
conversation id string |
ID of the conversation this message belongs to |
"615717df4b8fa06267cd2f73" |
conversation_type |
string | Type of conversation |
"direct" |
created_at |
date string | Creation date | "2021-10-01T17:14:55.613000+0300" |
direction |
string | Whether the message was sent or received |
"inbound" |
files |
[file object] |
Array of files attached to the message |
[] |
frm |
string | Originating phone number | "+17604509400" |
is_read |
boolean | Is the message marked as seen? |
false |
is_visible |
boolean | Is the message currently visible? |
true |
source_conversation_type |
string | Campaign or direct conversation message | "campaign" |
stamp_id |
UUID string | "b44c10de-1d7b-4914-ac68-6af475bc3236" |
|
success |
boolean | Was the message successfully sent? |
true |
text |
string | Content of the message |
"Hello" |
timezone |
string | Timezone of the sender | "Europe/Kiev" |
to |
string | Receiving phone number | "+19513360234" |
Texting Contact
A texting contact is the source or destination of text messages and participates in conversations.
| Field | Type | Description | Example |
|---|---|---|---|
id |
texting contact id string |
Internal ID | "61254ea64b8fa062670a3fc8" |
company_id |
company id string |
ID of the company |
"611ced1255c44a89f8df7cc0" |
first_name |
string | First name of texting contact |
"John" |
last_name |
string | Last name of texting contact |
"Smith" |
number |
string | Phone number | "+15555551234" |
Texting Number
A texting number is a dedicated phone number for sending and receiving text messages. It is associated with a single company and can be owned by multiple email addresses.
| Field | Type | Description | Example |
|---|---|---|---|
id |
texting number id string |
Internal ID | "61254e814b8fa062670a3e14" |
company_id |
company id string |
company ID |
"611ced1255c44a89f8df7cc0" |
number |
string | Phone number itself | "9513301234" |
ownership |
[string] | Email addresses that own this texting number |
["janedoe@example.com"] |
Voicemail
A voicemail is a message routed by an instance, containing an audio file that conveys the message.
| Field | Type | Description | Example |
|---|---|---|---|
_id |
voicemail id string |
Internal ID | "61015919b3c46160a6de8ea2" |
company_id |
company id string |
ID of the company |
"6101511f25781882dec1e427" |
extension_destination |
integer | extension number receiving the voicemail |
1001 |
extension_destination_id |
extension id string |
ID of the receiving extension |
"6101522c4c901ad517cb44a7" |
extension_source |
integer | extension number sending the voicemail |
1002 |
pbx |
instance uuid string |
UUID of the PBX instance |
"c62afa64-728a-575e-80bb-d5acb29a85a4" |
source_representation_name |
string | Representative name assigned | "John Doe" |
time_received |
date string | Date of receiving | "2021-07-28T16:18:17.404000Z" |
voicemail_email |
string | Email address | "johndoe@example.com" |
voicemail_file |
object | Audio file containing the voicemail |
- |
» id |
id string | Internal ID for the file | "6101591822c291ae68f260a9" |
» duration |
float | Length of audio | 0.2 |
» link |
string | URL leading to the file | "https://filehost.example.net/msg0000.wav" |
» name |
string | File name | "msg0000.wav" |
» size |
integer | Size of file in bytes | 3244 |
Webhook URL
Webhook URL holds the URL endpoint for any webhook.
| Field | Type | Description | Example |
|---|---|---|---|
id |
webhook url id string |
Internal ID | "6165720df936448755a444a8" |
company_id |
company id string |
ID of the company |
"611ced1255c44a89f8df7cc0" |
url |
string | Webhook URL | "webhook.example.com" |
Webhook Event
Webhook event holds a webhook callback that can be subscribed to.
The event type is one of
dial.action.starteddial.action.completedcall.action.hanguptexting.message.inbound
| Field | Type | Description | Example |
|---|---|---|---|
id |
webhook url id string |
Internal ID | "6165732029a740a320e8031f" |
company_id |
company id string |
ID of the company |
"611ced1255c44a89f8df7cc0" |
type |
string | Event | "texting.message.inbound" |