API Reference
v1.0
https://api.supportly.io/api/v1

Introduction

The Supportly API is a RESTful interface that lets you integrate customer support into your products. Manage conversations, contacts, teams, and more programmatically.

Base URL — All API requests should be made to: https://api.supportly.io/api/v1
Quick Start
Base URL
curl "https://api.supportly.io/api/v1/accounts/1/conversations" \
  -H "api_access_token: YOUR_TOKEN"
Base URL
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1/conversations")
req = Net::HTTP::Get.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
Base URL
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1/conversations', {
  headers: { 'api_access_token': 'YOUR_TOKEN' }
});
const data = await resp.json();
Base URL
import requests

resp = requests.get('https://api.supportly.io/api/v1/accounts/1/conversations',
    headers={'api_access_token': 'YOUR_TOKEN'})
data = resp.json()

Authentication

Supportly supports multiple authentication methods. Include your credentials in the request header to access protected endpoints.

API Access Token

Use a user or bot token via the api_access_token header. Best for server-side integrations.

OAuth 2.0 Bearer Token

Use Authorization: Bearer TOKEN header. Best for third-party apps acting on behalf of users.

User Session Cookie

Browser session-based auth for the Supportly dashboard. Not for API integrations.

Platform App Token

Platform-level tokens for multi-account management. Used by platform app developers.

Authentication
API Token Auth
curl "https://api.supportly.io/api/v1/accounts/1/conversations" \
  -H "api_access_token: YOUR_TOKEN"
Bearer Token Auth
curl "https://api.supportly.io/api/v1/accounts/1/conversations" \
  -H "Authorization: Bearer YOUR_OAUTH_TOKEN"
API Token Auth
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1/conversations")
req = Net::HTTP::Get.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)
API Token Auth
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1/conversations', {
  headers: { 'api_access_token': 'YOUR_TOKEN' }
});
const data = await resp.json();
API Token Auth
import requests

resp = requests.get('https://api.supportly.io/api/v1/accounts/1/conversations',
    headers={'api_access_token': 'YOUR_TOKEN'})
data = resp.json()

Rate Limits

API requests are rate-limited to ensure platform stability. Limits are applied per token on a sliding window.

Rate limit info is returned in response headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
429 Too Many Requests — If you exceed the rate limit, you'll receive a 429 response. Wait until X-RateLimit-Reset before retrying.
Rate Limit Headers
Response Headers
HTTP/1.1 200 OK
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 295
X-RateLimit-Reset: 1708003600
Rate Limited Response
429 Response
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1708003600
Retry-After: 30

{
  "errors": [
    {
      "message": "Rate limit exceeded. Please retry after 30 seconds."
    }
  ]
}

Error Handling

The API uses standard HTTP status codes. Errors return a JSON body with details about what went wrong.

200Success
201Created
400Bad Request — invalid parameters
401Unauthorized — invalid or missing credentials
403Forbidden — insufficient permissions
404Not Found — resource does not exist
422Unprocessable Entity — validation failed
429Too Many Requests — rate limit exceeded
500Internal Server Error
Error Response Format
Error Response
{
  "errors": [
    {
      "field": "email",
      "message": "has already been taken",
      "code": "taken"
    }
  ]
}

OAuth 2.0

Supportly supports the OAuth 2.0 Authorization Code flow, allowing third-party applications to securely access the API on behalf of users. Create OAuth apps in Settings → Developer Apps.

OAuth 2.0 Flow:
1. Redirect user to /oauth/authorize with your client ID and scopes.
2. User approves access on the consent screen.
3. Supportly redirects back with an authorization code.
4. Exchange code for access token via POST /oauth/token.
5. Use access token for authenticated API requests.
Available Scopes
readwriteconversations.readconversations.writecontacts.readcontacts.writemessages.readmessages.writeinboxes.readinboxes.writeteams.readteams.writelabels.readlabels.writereports.readagents.readagents.writeaccounts.readaccounts.writecampaigns.readcampaigns.writeautomations.readautomations.writecaptain.readcaptain.writewebhooks.readwebhooks.writeintegrations.readintegrations.write
OAuth 2.0 Flow Overview
Complete OAuth Flow
## Step 1: Redirect user to authorize
GET https://api.supportly.io/oauth/authorize
    ?client_id=YOUR_CLIENT_ID
    &redirect_uri=https://yourapp.com/callback
    &response_type=code
    &scope=conversations.read contacts.read

## Step 2: User approves → redirected back with code
https://yourapp.com/callback?code=AUTH_CODE&state=CSRF_TOKEN

## Step 3: Exchange code for access token
POST https://api.supportly.io/oauth/token
{
  "grant_type": "authorization_code",
  "code": "AUTH_CODE",
  "client_id": "YOUR_CLIENT_ID",
  "client_secret": "YOUR_CLIENT_SECRET",
  "redirect_uri": "https://yourapp.com/callback"
}

## Step 4: Use access token for API requests
GET https://api.supportly.io/api/v1/accounts/1/conversations
Authorization: Bearer YOUR_ACCESS_TOKEN

## Step 5: Refresh when expired
POST https://api.supportly.io/oauth/token
{ "grant_type": "refresh_token", "refresh_token": "..." }
GET/oauth/authorizeShow authorization consent page

Redirect users to this URL to begin the OAuth flow. Displays a consent page where the user can approve or deny access.

Query Parameters
client_idstringrequiredYour OAuth application's client ID
redirect_uristringrequiredURL to redirect after authorization. Must match a registered redirect URI.
response_typestringrequiredMust be code
scopestringSpace-separated list of requested scopes. Defaults to read.
statestringAn opaque value for CSRF protection. Returned unchanged in the callback.
OAuth Authorize
Example
GET https://api.supportly.io/oauth/authorize?
  client_id=your_client_id&
  redirect_uri=https://yourapp.com/callback&
  response_type=code&
  scope=conversations.read contacts.read&
  state=random_csrf_string
POST/oauth/tokenExchange code for access token

Exchange an authorization code for an access token and refresh token. The authorization code is single-use and expires in 10 minutes.

Body Parameters
grant_typestringrequiredMust be authorization_code
codestringrequiredThe authorization code received from the callback
client_idstringrequiredYour application's client ID
client_secretstringrequiredYour application's client secret
redirect_uristringrequiredMust match the redirect URI used in the authorize request
Token Exchange
Request
curl -X POST "https://api.supportly.io/oauth/token" \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "authorization_code",
    "code": "AUTH_CODE_HERE",
    "client_id": "your_client_id",
    "client_secret": "your_client_secret",
    "redirect_uri": "https://yourapp.com/callback"
  }'
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/oauth/token")
req = Net::HTTP::Post.new(uri)
req['Content-Type'] = 'application/json'
req.body = {
  grant_type: 'authorization_code',
  code: 'AUTH_CODE_HERE',
  client_id: 'your_client_id',
  client_secret: 'your_client_secret',
  redirect_uri: 'https://yourapp.com/callback'
}.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)
Request
const resp = await fetch('https://api.supportly.io/oauth/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    grant_type: 'authorization_code',
    code: 'AUTH_CODE_HERE',
    client_id: 'your_client_id',
    client_secret: 'your_client_secret',
    redirect_uri: 'https://yourapp.com/callback'
  })
});
const data = await resp.json();
Request
import requests

resp = requests.post('https://api.supportly.io/oauth/token', json={
    'grant_type': 'authorization_code',
    'code': 'AUTH_CODE_HERE',
    'client_id': 'your_client_id',
    'client_secret': 'your_client_secret',
    'redirect_uri': 'https://yourapp.com/callback'
})
data = resp.json()
Response (200)
{
  "access_token": "eyJhbGciOiJIUzI1NiJ9...",
  "token_type": "Bearer",
  "expires_in": 86400,
  "refresh_token": "dGhpcyBpcyBhIHJlZnJlc2g...",
  "scope": "conversations.read contacts.read",
  "created_at": 1708000000
}
POST/oauth/tokenRefresh an expired access token

Use a refresh token to obtain a new access token when the current one expires. Access tokens expire after 24 hours.

Body Parameters
grant_typestringrequiredMust be refresh_token
refresh_tokenstringrequiredThe refresh token from a previous token exchange
client_idstringrequiredYour application's client ID
client_secretstringrequiredYour application's client secret
Refresh Token
Request
curl -X POST "https://api.supportly.io/oauth/token" \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "refresh_token",
    "refresh_token": "YOUR_REFRESH_TOKEN",
    "client_id": "your_client_id",
    "client_secret": "your_client_secret"
  }'
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/oauth/token")
req = Net::HTTP::Post.new(uri)
req['Content-Type'] = 'application/json'
req.body = {
  grant_type: 'refresh_token',
  refresh_token: 'YOUR_REFRESH_TOKEN',
  client_id: 'your_client_id',
  client_secret: 'your_client_secret'
}.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
Request
const resp = await fetch('https://api.supportly.io/oauth/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    grant_type: 'refresh_token',
    refresh_token: 'YOUR_REFRESH_TOKEN',
    client_id: 'your_client_id',
    client_secret: 'your_client_secret'
  })
});
Request
import requests

resp = requests.post('https://api.supportly.io/oauth/token', json={
    'grant_type': 'refresh_token',
    'refresh_token': 'YOUR_REFRESH_TOKEN',
    'client_id': 'your_client_id',
    'client_secret': 'your_client_secret'
})
POST/oauth/revokeRevoke an access or refresh token

Immediately invalidate an access token or refresh token. Use this when a user disconnects your app.

Body Parameters
tokenstringrequiredThe access token or refresh token to revoke
client_idstringrequiredYour application's client ID
client_secretstringrequiredYour application's client secret
Revoke Token
Request
curl -X POST "https://api.supportly.io/oauth/revoke" \
  -H "Content-Type: application/json" \
  -d '{
    "token": "TOKEN_TO_REVOKE",
    "client_id": "your_client_id",
    "client_secret": "your_client_secret"
  }'
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/oauth/revoke")
req = Net::HTTP::Post.new(uri)
req['Content-Type'] = 'application/json'
req.body = { token: 'TOKEN_TO_REVOKE', client_id: 'your_client_id', client_secret: 'your_client_secret' }.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
Request
const resp = await fetch('https://api.supportly.io/oauth/revoke', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    token: 'TOKEN_TO_REVOKE',
    client_id: 'your_client_id',
    client_secret: 'your_client_secret'
  })
});
Request
import requests

resp = requests.post('https://api.supportly.io/oauth/revoke', json={
    'token': 'TOKEN_TO_REVOKE',
    'client_id': 'your_client_id',
    'client_secret': 'your_client_secret'
})

Conversations

Conversations are the core of Supportly. Each conversation represents an interaction thread between a customer and your team across any channel.

GET/api/v1/accounts/{account_id}/conversations

Retrieve a paginated list of conversations. Filter by status, assignee, inbox, team, and labels.

Query Parameters
statusstringFilter by status: open, resolved, pending, snoozed, all
assignee_typestringFilter by assignment: me, unassigned, assigned, all
inbox_idintegerFilter conversations by inbox
team_idintegerFilter conversations by team
labels[]arrayFilter by labels
pageintegerPage number for pagination (default: 1)
200Returns paginated list of conversations with metadata
401Unauthorized
POST/api/v1/accounts/{account_id}/conversations

Create a new conversation. Requires an inbox and contact to start the thread.

Body Parameters
inbox_idintegerrequiredThe inbox to create the conversation in
contact_idintegerrequiredThe contact associated with this conversation
messageobjectInitial message: { "content": "Hello!" }
assignee_idintegerAgent ID to assign the conversation to
team_idintegerTeam ID to assign the conversation to
statusstringInitial status: open, pending
GET/api/v1/accounts/{account_id}/conversations/{id}

Retrieve a single conversation by its display ID, including metadata, participants, and assignment info.

PATCH/api/v1/accounts/{account_id}/conversations/{id}

Update conversation properties like status, priority, or custom attributes.

Body Parameters
statusstringopen, resolved, pending, snoozed
prioritystringnone, low, medium, high, urgent
snoozed_untilintegerUnix timestamp for snooze end (when status is snoozed)
List Conversations
Request
curl "https://api.supportly.io/api/v1/accounts/1/conversations?status=open&page=1" \
  -H "api_access_token: YOUR_TOKEN"
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1/conversations?status=open&page=1")
req = Net::HTTP::Get.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)
Request
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1/conversations?status=open&page=1', {
  headers: { 'api_access_token': 'YOUR_TOKEN' }
});
const data = await resp.json();
Request
import requests

resp = requests.get('https://api.supportly.io/api/v1/accounts/1/conversations',
    params={'status': 'open', 'page': 1},
    headers={'api_access_token': 'YOUR_TOKEN'})
data = resp.json()
Create Conversation
Request
curl -X POST "https://api.supportly.io/api/v1/accounts/1/conversations" \
  -H "api_access_token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "inbox_id": 1,
    "contact_id": 42,
    "message": { "content": "Hello, I need help!" },
    "status": "open"
  }'
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1/conversations")
req = Net::HTTP::Post.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
req['Content-Type'] = 'application/json'
req.body = { inbox_id: 1, contact_id: 42, message: { content: 'Hello, I need help!' }, status: 'open' }.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
Request
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1/conversations', {
  method: 'POST',
  headers: { 'api_access_token': 'YOUR_TOKEN', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    inbox_id: 1, contact_id: 42,
    message: { content: 'Hello, I need help!' }, status: 'open'
  })
});
Request
import requests

resp = requests.post('https://api.supportly.io/api/v1/accounts/1/conversations',
    headers={'api_access_token': 'YOUR_TOKEN'},
    json={'inbox_id': 1, 'contact_id': 42,
          'message': {'content': 'Hello, I need help!'}, 'status': 'open'})
data = resp.json()

Messages

Messages are individual communications within a conversation. Send replies, notes, and attachments.

GET/api/v1/accounts/{account_id}/conversations/{conversation_id}/messages

Retrieve all messages for a specific conversation, ordered chronologically.

POST/api/v1/accounts/{account_id}/conversations/{conversation_id}/messages

Send a new message in a conversation. Supports text, private notes, and file attachments.

Body Parameters
contentstringrequiredThe message text content
message_typestringoutgoing (reply to customer) or activity (private note)
privatebooleanIf true, creates an internal note visible only to agents
content_attributesobjectAdditional message metadata
DELETE/api/v1/accounts/{account_id}/conversations/{conversation_id}/messages/{id}

Delete a specific message from a conversation. Cannot be undone.

Send Message
Request
curl -X POST "https://api.supportly.io/api/v1/accounts/1/conversations/42/messages" \
  -H "api_access_token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "content": "Thanks for reaching out!", "message_type": "outgoing" }'
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1/conversations/42/messages")
req = Net::HTTP::Post.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
req['Content-Type'] = 'application/json'
req.body = { content: 'Thanks for reaching out!', message_type: 'outgoing' }.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
Request
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1/conversations/42/messages', {
  method: 'POST',
  headers: { 'api_access_token': 'YOUR_TOKEN', 'Content-Type': 'application/json' },
  body: JSON.stringify({ content: 'Thanks for reaching out!', message_type: 'outgoing' })
});
Request
import requests

resp = requests.post('https://api.supportly.io/api/v1/accounts/1/conversations/42/messages',
    headers={'api_access_token': 'YOUR_TOKEN'},
    json={'content': 'Thanks for reaching out!', 'message_type': 'outgoing'})

Contacts

Contacts represent individuals who interact with your team. Manage customer profiles, custom attributes, and conversation history.

GET/api/v1/accounts/{account_id}/contacts

Retrieve a paginated list of all contacts in your account.

Query Parameters
pageintegerPage number (default: 1, 15 per page)
sortstringSort field: name, email, phone_number, last_activity_at, created_at
order_bystringasc or desc
POST/api/v1/accounts/{account_id}/contacts

Create a new contact in your account.

Body Parameters
namestringContact's full name
emailstringContact's email address
phone_numberstringContact's phone number (E.164 format)
avatar_urlstringURL to the contact's avatar image
identifierstringUnique external identifier for the contact
custom_attributesobjectKey-value pairs of custom attributes
GET/api/v1/accounts/{account_id}/contacts/{id}

Retrieve a single contact by ID, including all profile data and custom attributes.

PATCH/api/v1/accounts/{account_id}/contacts/{id}

Update contact profile information, custom attributes, or avatar.

DELETE/api/v1/accounts/{account_id}/contacts/{id}

Permanently delete a contact and all associated data. This action cannot be undone.

GET/api/v1/accounts/{account_id}/contacts/{id}/conversations

Retrieve all conversations associated with a specific contact.

GET/api/v1/accounts/{account_id}/search?q={query}

Search contacts by name, email, phone number, or identifier.

Query Parameters
qstringrequiredSearch query string
pageintegerPage number
Create Contact
Request
curl -X POST "https://api.supportly.io/api/v1/accounts/1/contacts" \
  -H "api_access_token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Jane Smith",
    "email": "jane@example.com",
    "phone_number": "+1234567890",
    "custom_attributes": { "plan": "enterprise" }
  }'
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1/contacts")
req = Net::HTTP::Post.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
req['Content-Type'] = 'application/json'
req.body = {
  name: 'Jane Smith', email: 'jane@example.com',
  phone_number: '+1234567890',
  custom_attributes: { plan: 'enterprise' }
}.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
Request
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1/contacts', {
  method: 'POST',
  headers: { 'api_access_token': 'YOUR_TOKEN', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    name: 'Jane Smith', email: 'jane@example.com',
    phone_number: '+1234567890',
    custom_attributes: { plan: 'enterprise' }
  })
});
Request
import requests

resp = requests.post('https://api.supportly.io/api/v1/accounts/1/contacts',
    headers={'api_access_token': 'YOUR_TOKEN'},
    json={'name': 'Jane Smith', 'email': 'jane@example.com',
          'phone_number': '+1234567890',
          'custom_attributes': {'plan': 'enterprise'}})

Inboxes

Inboxes are communication channels (website chat, email, social media, API) where customer conversations originate.

GET/api/v1/accounts/{account_id}/inboxes

Returns all inboxes configured for the account.

GET/api/v1/accounts/{account_id}/inboxes/{id}

Retrieve details for a specific inbox including channel configuration.

POST/api/v1/accounts/{account_id}/inboxes

Create a new inbox. Required fields depend on the channel type (web, email, api, etc.).

Body Parameters
namestringrequiredInbox display name
channelobjectrequiredChannel configuration including type
List Inboxes
Request
curl "https://api.supportly.io/api/v1/accounts/1/inboxes" \
  -H "api_access_token: YOUR_TOKEN"
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1/inboxes")
req = Net::HTTP::Get.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)
Request
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1/inboxes', {
  headers: { 'api_access_token': 'YOUR_TOKEN' }
});
const data = await resp.json();
Request
import requests

resp = requests.get('https://api.supportly.io/api/v1/accounts/1/inboxes',
    headers={'api_access_token': 'YOUR_TOKEN'})
data = resp.json()

Agents

Agents are team members who handle conversations. Manage agent accounts, availability, and assignments.

GET/api/v1/accounts/{account_id}/agents

Returns all agents (team members) for the account.

POST/api/v1/accounts/{account_id}/agents

Invite a new agent to your account.

Body Parameters
namestringrequiredAgent's full name
emailstringrequiredAgent's email address
rolestringrequiredagent or administrator
PATCH/api/v1/accounts/{account_id}/agents/{id}

Update an agent's name, role, or availability status.

DELETE/api/v1/accounts/{account_id}/agents/{id}

Remove an agent from your account. Their conversations will be unassigned.

List Agents
Request
curl "https://api.supportly.io/api/v1/accounts/1/agents" \
  -H "api_access_token: YOUR_TOKEN"
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1/agents")
req = Net::HTTP::Get.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)
Request
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1/agents', {
  headers: { 'api_access_token': 'YOUR_TOKEN' }
});
const data = await resp.json();
Request
import requests

resp = requests.get('https://api.supportly.io/api/v1/accounts/1/agents',
    headers={'api_access_token': 'YOUR_TOKEN'})
data = resp.json()

Teams

Teams group agents together for organized assignment, routing, and management of conversations.

GET/api/v1/accounts/{account_id}/teams

Returns all teams in the account.

POST/api/v1/accounts/{account_id}/teams

Create a new team.

Body Parameters
namestringrequiredTeam name
descriptionstringTeam description
allow_auto_assignbooleanEnable auto-assignment for this team
Create Team
Request
curl -X POST "https://api.supportly.io/api/v1/accounts/1/teams" \
  -H "api_access_token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Sales Team",
    "description": "Handles all sales inquiries",
    "allow_auto_assign": true
  }'
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1/teams")
req = Net::HTTP::Post.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
req['Content-Type'] = 'application/json'
req.body = {
  name: 'Sales Team',
  description: 'Handles all sales inquiries',
  allow_auto_assign: true
}.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)
Request
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1/teams', {
  method: 'POST',
  headers: { 'api_access_token': 'YOUR_TOKEN', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    name: 'Sales Team',
    description: 'Handles all sales inquiries',
    allow_auto_assign: true
  })
});
const data = await resp.json();
Request
import requests

resp = requests.post('https://api.supportly.io/api/v1/accounts/1/teams',
    headers={'api_access_token': 'YOUR_TOKEN'},
    json={'name': 'Sales Team',
          'description': 'Handles all sales inquiries',
          'allow_auto_assign': True})
data = resp.json()

Labels

Organize conversations and contacts with custom labels for categorization and filtering.

GET/api/v1/accounts/{account_id}/labels

Returns all labels configured for the account.

POST/api/v1/accounts/{account_id}/labels

Create a new label.

Body Parameters
titlestringrequiredLabel name (lowercase, no spaces)
descriptionstringLabel description
colorstringHex color code (e.g., #FF5733)
show_on_sidebarbooleanWhether to show in the sidebar
Create Label
Request
curl -X POST "https://api.supportly.io/api/v1/accounts/1/labels" \
  -H "api_access_token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "priority-customer",
    "description": "High-priority customer requests",
    "color": "#FF5733",
    "show_on_sidebar": true
  }'
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1/labels")
req = Net::HTTP::Post.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
req['Content-Type'] = 'application/json'
req.body = {
  title: 'priority-customer',
  description: 'High-priority customer requests',
  color: '#FF5733',
  show_on_sidebar: true
}.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)
Request
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1/labels', {
  method: 'POST',
  headers: { 'api_access_token': 'YOUR_TOKEN', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    title: 'priority-customer',
    description: 'High-priority customer requests',
    color: '#FF5733',
    show_on_sidebar: true
  })
});
const data = await resp.json();
Request
import requests

resp = requests.post('https://api.supportly.io/api/v1/accounts/1/labels',
    headers={'api_access_token': 'YOUR_TOKEN'},
    json={'title': 'priority-customer',
          'description': 'High-priority customer requests',
          'color': '#FF5733',
          'show_on_sidebar': True})
data = resp.json()

Automation Rules

Automate repetitive tasks with rules that trigger actions based on conversation events and conditions.

GET/api/v1/accounts/{account_id}/automation_rules

Returns all automation rules for the account.

POST/api/v1/accounts/{account_id}/automation_rules

Create an automation rule with event triggers, conditions, and actions.

List Automation Rules
Request
curl "https://api.supportly.io/api/v1/accounts/1/automation_rules" \
  -H "api_access_token: YOUR_TOKEN"
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1/automation_rules")
req = Net::HTTP::Get.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)
Request
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1/automation_rules', {
  headers: { 'api_access_token': 'YOUR_TOKEN' }
});
const data = await resp.json();
Request
import requests

resp = requests.get('https://api.supportly.io/api/v1/accounts/1/automation_rules',
    headers={'api_access_token': 'YOUR_TOKEN'})
data = resp.json()

Canned Responses

Pre-written reply templates that agents can quickly insert into conversations.

GET/api/v1/accounts/{account_id}/canned_responses

Returns all canned responses. Optionally search by keyword.

POST/api/v1/accounts/{account_id}/canned_responses

Create a canned response template.

Body Parameters
short_codestringrequiredShortcut code for quick access
contentstringrequiredTemplate content
Create Canned Response
Request
curl -X POST "https://api.supportly.io/api/v1/accounts/1/canned_responses" \
  -H "api_access_token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "short_code": "greeting",
    "content": "Hello! Thanks for reaching out. How can I help you today?"
  }'
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1/canned_responses")
req = Net::HTTP::Post.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
req['Content-Type'] = 'application/json'
req.body = {
  short_code: 'greeting',
  content: 'Hello! Thanks for reaching out. How can I help you today?'
}.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)
Request
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1/canned_responses', {
  method: 'POST',
  headers: { 'api_access_token': 'YOUR_TOKEN', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    short_code: 'greeting',
    content: 'Hello! Thanks for reaching out. How can I help you today?'
  })
});
const data = await resp.json();
Request
import requests

resp = requests.post('https://api.supportly.io/api/v1/accounts/1/canned_responses',
    headers={'api_access_token': 'YOUR_TOKEN'},
    json={'short_code': 'greeting',
          'content': 'Hello! Thanks for reaching out. How can I help you today?'})
data = resp.json()

Campaigns

Create and manage outbound campaigns to engage customers proactively.

GET/api/v1/accounts/{account_id}/campaigns

Returns all campaigns for the account.

POST/api/v1/accounts/{account_id}/campaigns

Create a new campaign.

Body Parameters
titlestringrequiredCampaign title
messagestringrequiredCampaign message content
inbox_idintegerrequiredInbox to send from
Create Campaign
Request
curl -X POST "https://api.supportly.io/api/v1/accounts/1/campaigns" \
  -H "api_access_token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Welcome Campaign",
    "message": "Hi there! Welcome to our platform. How can we assist you?",
    "inbox_id": 1
  }'
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1/campaigns")
req = Net::HTTP::Post.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
req['Content-Type'] = 'application/json'
req.body = {
  title: 'Welcome Campaign',
  message: 'Hi there! Welcome to our platform. How can we assist you?',
  inbox_id: 1
}.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)
Request
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1/campaigns', {
  method: 'POST',
  headers: { 'api_access_token': 'YOUR_TOKEN', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    title: 'Welcome Campaign',
    message: 'Hi there! Welcome to our platform. How can we assist you?',
    inbox_id: 1
  })
});
const data = await resp.json();
Request
import requests

resp = requests.post('https://api.supportly.io/api/v1/accounts/1/campaigns',
    headers={'api_access_token': 'YOUR_TOKEN'},
    json={'title': 'Welcome Campaign',
          'message': 'Hi there! Welcome to our platform. How can we assist you?',
          'inbox_id': 1})
data = resp.json()

Webhooks

Receive real-time HTTP callbacks when events occur in your Supportly account.

Available Events: conversation_created, conversation_status_changed, conversation_updated, message_created, message_updated, contact_created, contact_updated, webwidget_triggered
GET/api/v1/accounts/{account_id}/webhooks

Returns all configured webhooks.

POST/api/v1/accounts/{account_id}/webhooks

Create a webhook subscription.

Body Parameters
urlstringrequiredThe URL to receive webhook payloads
subscriptionsarrayList of events to subscribe to
Webhook Payload
Event Payload
{
  "event": "message_created",
  "id": 42,
  "content": "Hello!",
  "message_type": "incoming",
  "conversation": {
    "id": 1,
    "status": "open"
  }
}

Captain AI

Leverage AI-powered features for intelligent assistance, knowledge management, and automated responses.

GET/api/v1/accounts/{account_id}/captain/assistants

Returns all AI assistants configured for the account.

GET/api/v1/accounts/{account_id}/captain/documents

Returns all knowledge base documents used by Captain AI.

POST/api/v1/accounts/{account_id}/captain/documents

Upload a document to the AI knowledge base.

Body Parameters
titlestringrequiredDocument title
contentstringrequiredDocument content
POST/api/v1/accounts/{account_id}/captain/copilot/threads

Create a new copilot conversation thread for agent assistance.

Upload Document
Request
curl -X POST "https://api.supportly.io/api/v1/accounts/1/captain/documents" \
  -H "api_access_token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Product FAQ",
    "content": "## Frequently Asked Questions\n\nQ: How do I reset my password?\nA: Go to Settings > Security > Reset Password."
  }'
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1/captain/documents")
req = Net::HTTP::Post.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
req['Content-Type'] = 'application/json'
req.body = {
  title: 'Product FAQ',
  content: '## Frequently Asked Questions\n\nQ: How do I reset my password?\nA: Go to Settings > Security > Reset Password.'
}.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)
Request
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1/captain/documents', {
  method: 'POST',
  headers: { 'api_access_token': 'YOUR_TOKEN', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    title: 'Product FAQ',
    content: '## Frequently Asked Questions...'
  })
});
const data = await resp.json();
Request
import requests

resp = requests.post('https://api.supportly.io/api/v1/accounts/1/captain/documents',
    headers={'api_access_token': 'YOUR_TOKEN'},
    json={'title': 'Product FAQ',
          'content': '## Frequently Asked Questions...'})
data = resp.json()

Portals

Help center portals provide self-service knowledge bases for your customers.

GET/api/v1/accounts/{account_id}/portals

Returns all help center portals.

POST/api/v1/accounts/{account_id}/portals

Create a new help center portal.

Body Parameters
namestringrequiredPortal name
slugstringrequiredURL-friendly identifier
colorstringBrand color hex code
Create Portal
Request
curl -X POST "https://api.supportly.io/api/v1/accounts/1/portals" \
  -H "api_access_token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Help Center",
    "slug": "help-center",
    "color": "#1B83FF"
  }'
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1/portals")
req = Net::HTTP::Post.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
req['Content-Type'] = 'application/json'
req.body = {
  name: 'Help Center',
  slug: 'help-center',
  color: '#1B83FF'
}.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)
Request
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1/portals', {
  method: 'POST',
  headers: { 'api_access_token': 'YOUR_TOKEN', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    name: 'Help Center',
    slug: 'help-center',
    color: '#1B83FF'
  })
});
const data = await resp.json();
Request
import requests

resp = requests.post('https://api.supportly.io/api/v1/accounts/1/portals',
    headers={'api_access_token': 'YOUR_TOKEN'},
    json={'name': 'Help Center',
          'slug': 'help-center',
          'color': '#1B83FF'})
data = resp.json()

Articles

Help center articles provide self-service support content for your customers.

GET/api/v1/accounts/{account_id}/portals/{portal_slug}/articles

Returns all articles for a portal. Supports filtering by category and status.

POST/api/v1/accounts/{account_id}/portals/{portal_slug}/articles

Create a new help center article.

Body Parameters
titlestringrequiredArticle title
contentstringrequiredArticle content (Markdown)
statusstringdraft or published
category_idintegerCategory ID to organize the article
PATCH/api/v1/accounts/{account_id}/portals/{portal_slug}/articles/{id}

Update an existing article's content, title, or status.

DELETE/api/v1/accounts/{account_id}/portals/{portal_slug}/articles/{id}

Delete an article from the help center.

Create Article
Request
curl -X POST "https://api.supportly.io/api/v1/accounts/1/portals/my-portal/articles" \
  -H "api_access_token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Getting Started with Supportly",
    "content": "## Welcome\nThis guide will help you...",
    "status": "published",
    "category_id": 1
  }'
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1/portals/my-portal/articles")
req = Net::HTTP::Post.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
req['Content-Type'] = 'application/json'
req.body = { title: 'Getting Started with Supportly', content: '## Welcome...', status: 'published', category_id: 1 }.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
Request
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1/portals/my-portal/articles', {
  method: 'POST',
  headers: { 'api_access_token': 'YOUR_TOKEN', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    title: 'Getting Started with Supportly',
    content: '## Welcome...', status: 'published', category_id: 1
  })
});
Request
import requests

resp = requests.post('https://api.supportly.io/api/v1/accounts/1/portals/my-portal/articles',
    headers={'api_access_token': 'YOUR_TOKEN'},
    json={'title': 'Getting Started with Supportly',
          'content': '## Welcome...', 'status': 'published', 'category_id': 1})

Categories

Organize help center articles into categories for better navigation.

GET/api/v1/accounts/{account_id}/portals/{portal_slug}/categories

Returns all categories for a portal.

POST/api/v1/accounts/{account_id}/portals/{portal_slug}/categories

Create a new category.

Body Parameters
namestringrequiredCategory name
descriptionstringCategory description
localestringLocale code (e.g., en)
Create Category
Request
curl -X POST "https://api.supportly.io/api/v1/accounts/1/portals/my-portal/categories" \
  -H "api_access_token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Getting Started",
    "description": "Introductory guides and tutorials",
    "locale": "en"
  }'
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1/portals/my-portal/categories")
req = Net::HTTP::Post.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
req['Content-Type'] = 'application/json'
req.body = {
  name: 'Getting Started',
  description: 'Introductory guides and tutorials',
  locale: 'en'
}.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)
Request
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1/portals/my-portal/categories', {
  method: 'POST',
  headers: { 'api_access_token': 'YOUR_TOKEN', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    name: 'Getting Started',
    description: 'Introductory guides and tutorials',
    locale: 'en'
  })
});
const data = await resp.json();
Request
import requests

resp = requests.post('https://api.supportly.io/api/v1/accounts/1/portals/my-portal/categories',
    headers={'api_access_token': 'YOUR_TOKEN'},
    json={'name': 'Getting Started',
          'description': 'Introductory guides and tutorials',
          'locale': 'en'})
data = resp.json()

Companies

Companies represent organizations that your contacts belong to. Group contacts by company for account-based support.

GET/api/v1/accounts/{account_id}/companies

Returns all companies in your account.

POST/api/v1/accounts/{account_id}/companies

Create a new company.

Body Parameters
namestringrequiredCompany name
domainstringCompany website domain
industrystringIndustry vertical
employee_countintegerNumber of employees
PATCH/api/v1/accounts/{account_id}/companies/{id}

Update company information.

DELETE/api/v1/accounts/{account_id}/companies/{id}

Delete a company. Contacts will be unlinked but not deleted.

Create Company
Request
curl -X POST "https://api.supportly.io/api/v1/accounts/1/companies" \
  -H "api_access_token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Inc",
    "domain": "acme.com",
    "industry": "Technology",
    "employee_count": 150
  }'
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1/companies")
req = Net::HTTP::Post.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
req['Content-Type'] = 'application/json'
req.body = { name: 'Acme Inc', domain: 'acme.com', industry: 'Technology', employee_count: 150 }.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
Request
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1/companies', {
  method: 'POST',
  headers: { 'api_access_token': 'YOUR_TOKEN', 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'Acme Inc', domain: 'acme.com', industry: 'Technology', employee_count: 150 })
});
Request
import requests

resp = requests.post('https://api.supportly.io/api/v1/accounts/1/companies',
    headers={'api_access_token': 'YOUR_TOKEN'},
    json={'name': 'Acme Inc', 'domain': 'acme.com',
          'industry': 'Technology', 'employee_count': 150})

Integrations

Connect third-party services like Slack, Dialogflow, and OpenAI to extend Supportly's capabilities.

GET/api/v1/accounts/{account_id}/integrations/apps

Returns all available integration apps and their connection status.

POST/api/v1/accounts/{account_id}/integrations/hooks

Create a new integration connection (hook).

DELETE/api/v1/accounts/{account_id}/integrations/hooks/{id}

Disconnect an integration.

Integration Connect Response
Response
{
  "authorization_url": "https://provider.com/oauth/authorize?client_id=...",
  "code_verifier": "abc123..."  // Only for PKCE providers
}

Data Migration

Import data from other platforms like Intercom, Zendesk, and Freshdesk into Supportly.

POST/api/v1/accounts/{account_id}/data_migrations

Start a data migration from a supported platform.

Body Parameters
sourcestringrequiredSource platform: intercom, zendesk, freshdesk
credentialsobjectrequiredAuthentication credentials for the source platform
GET/api/v1/accounts/{account_id}/data_migrations/{id}

Check the status of a data migration.

Migration Status
Response
{
  "id": 1,
  "source": "intercom",
  "status": "in_progress",
  "progress": 65,
  "records_imported": 1250,
  "total_records": 1920
}

Developer OAuth Apps

Create and manage OAuth 2.0 applications for third-party integrations with Supportly.

GET/api/v1/accounts/{account_id}/developer_apps

Returns all OAuth applications created by your account.

POST/api/v1/accounts/{account_id}/developer_apps

Register a new OAuth application.

Body Parameters
namestringrequiredApplication name
redirect_urisarrayrequiredArray of allowed redirect URIs
scopesarrayRequested OAuth scopes
GET/oauth/token/info

Introspect the current OAuth token to retrieve scope, expiry, and ownership details.

Developer App Response
Create Response
{
  "id": 1,
  "name": "My Integration",
  "client_id": "abc123...",
  "client_secret": "secret_shown_only_once...",
  "redirect_uris": ["https://yourapp.com/callback"],
  "scopes": ["conversations.read", "contacts.read"]
}
Token Introspection
GET /oauth/token/info Response
{
  "resource_owner_id": 42,
  "scope": "conversations.read contacts.read",
  "expires_in": 82400,
  "application": { "uid": "abc123..." },
  "created_at": 1708000000
}

Account

Manage your Supportly account settings, including name, locale, and auto-resolve configuration.

GET/api/v1/accounts/{account_id}

Retrieve account details including settings and feature flags.

PATCH/api/v1/accounts/{account_id}

Update account settings.

Body Parameters
namestringAccount name
localestringDefault locale
auto_resolve_durationintegerAuto-resolve conversations after N days
Get Account Info
Request
curl "https://api.supportly.io/api/v1/accounts/1" \
  -H "api_access_token: YOUR_TOKEN"
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1")
req = Net::HTTP::Get.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)
Request
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1', {
  headers: { 'api_access_token': 'YOUR_TOKEN' }
});
const data = await resp.json();
Request
import requests

resp = requests.get('https://api.supportly.io/api/v1/accounts/1',
    headers={'api_access_token': 'YOUR_TOKEN'})
data = resp.json()

Custom Attributes

Define custom data fields for conversations and contacts to capture business-specific information.

GET/api/v1/accounts/{account_id}/custom_attribute_definitions

Returns all custom attribute definitions.

POST/api/v1/accounts/{account_id}/custom_attribute_definitions

Define a new custom attribute.

Body Parameters
attribute_display_namestringrequiredDisplay name for the attribute
attribute_display_typestringrequiredType: text, number, link, date, list, checkbox
attribute_modelstringrequiredconversation_attribute or contact_attribute
Create Custom Attribute
Request
curl -X POST "https://api.supportly.io/api/v1/accounts/1/custom_attribute_definitions" \
  -H "api_access_token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "attribute_display_name": "Subscription Plan",
    "attribute_display_type": "list",
    "attribute_model": "contact_attribute"
  }'
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v1/accounts/1/custom_attribute_definitions")
req = Net::HTTP::Post.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
req['Content-Type'] = 'application/json'
req.body = {
  attribute_display_name: 'Subscription Plan',
  attribute_display_type: 'list',
  attribute_model: 'contact_attribute'
}.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)
Request
const resp = await fetch('https://api.supportly.io/api/v1/accounts/1/custom_attribute_definitions', {
  method: 'POST',
  headers: { 'api_access_token': 'YOUR_TOKEN', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    attribute_display_name: 'Subscription Plan',
    attribute_display_type: 'list',
    attribute_model: 'contact_attribute'
  })
});
const data = await resp.json();
Request
import requests

resp = requests.post('https://api.supportly.io/api/v1/accounts/1/custom_attribute_definitions',
    headers={'api_access_token': 'YOUR_TOKEN'},
    json={'attribute_display_name': 'Subscription Plan',
          'attribute_display_type': 'list',
          'attribute_model': 'contact_attribute'})
data = resp.json()

Reports

Access analytics and performance reports for agents, inboxes, and teams.

GET/api/v2/accounts/{account_id}/reports/agents

Get agent performance metrics for a date range.

Query Parameters
sincestringrequiredStart date (ISO 8601)
untilstringrequiredEnd date (ISO 8601)
GET/api/v2/accounts/{account_id}/reports/inboxes

Get inbox-level performance metrics.

GET/api/v2/accounts/{account_id}/reports/teams

Get team-level performance metrics.

Get Agent Reports
Request
curl "https://api.supportly.io/api/v2/accounts/1/reports/agents?since=2024-01-01&until=2024-01-31" \
  -H "api_access_token: YOUR_TOKEN"
Request
require 'net/http'
require 'json'

uri = URI("https://api.supportly.io/api/v2/accounts/1/reports/agents?since=2024-01-01&until=2024-01-31")
req = Net::HTTP::Get.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)
Request
const resp = await fetch('https://api.supportly.io/api/v2/accounts/1/reports/agents?since=2024-01-01&until=2024-01-31', {
  headers: { 'api_access_token': 'YOUR_TOKEN' }
});
const data = await resp.json();
Request
import requests

resp = requests.get('https://api.supportly.io/api/v2/accounts/1/reports/agents',
    headers={'api_access_token': 'YOUR_TOKEN'},
    params={'since': '2024-01-01', 'until': '2024-01-31'})
data = resp.json()