API Documentation
API Documentation
This quickstart takes you from an empty integration to your first authenticated Sonarly API request. You will create an API key, call the public API, read the response envelope, and use the returned account ID in the next workflow.
You need a Sonarly account with access to the workspace you want to automate. If you do not have one yet, sign up first, then open the dashboard and create an API key.
All public API requests use this base URL:
https://api.sonarly.ioEvery endpoint in these docs is versioned under /v1.
Keep API keys on your server. Do not expose them in browser code, mobile apps, public repositories, logs, or shared screenshots.
The account discovery endpoint works with any valid API key. If permissions are grouped by feature, choose the read permissions for the resources you want to inspect next, such as audiences:read or prospecting:read.
Use the API key as a Bearer token in the Authorization header. The fastest way to confirm the key works is to list the account groups available to it:
curl https://api.sonarly.io/v1/accounts \
-H "Authorization: Bearer sk_live_your_api_key_here" \
-H "Accept: application/json"The request returns the account groups your key can access:
{
"success": true,
"data": {
"items": [
{
"id": "507f1f77bcf86cd799439011",
"name": "Acme Growth",
"createdAt": "2026-05-01T12:00:00.000Z"
}
],
"nextCursor": null,
"hasMore": false
},
"error": null
Save the data.items[0].id value as your accountGroupId. Most Sonarly API routes are scoped to an account group.
If the response is 401, the key is missing, invalid, or revoked. If the response is 403, the key is valid but does not have the permission needed by that endpoint.
Sonarly wraps every response in the same envelope so your client can handle success, validation, authorization, and upstream errors consistently.
| Field | Success value | Error value | Description |
|---|---|---|---|
success | true | false | Whether the request completed successfully |
data | Response body | null | The route-specific payload |
error |
An error response uses the same shape:
{
"success": false,
"data": null,
"error": {
"code": "SCOPE_DENIED",
"message": "The API key does not have permission to access this resource."
},
"traceId": "trace_01HYR7X8Q4M8K9P2V6N3B5C0D1"
}Common error codes include UNAUTHORIZED, SCOPE_DENIED, NOT_FOUND, VALIDATION_ERROR, RATE_LIMIT_EXCEEDED, QUOTA_EXCEEDED, AUDIENCE_NOT_READY, and INSUFFICIENT_CREDITS.
After you have an accountGroupId, list audiences to see the imported prospect lists available in the account group:
curl "https://api.sonarly.io/v1/accounts/507f1f77bcf86cd799439011/audiences?limit=10" \
-H "Authorization: Bearer sk_live_your_api_key_here" \
-H "Accept: application/json"That response is paginated:
{
"success": true,
"data": {
"items": [
{
"id": "aud_01HYR8B9P4D6Y2A7C3E1F0G5H9",
"name": "Berlin Tech Leaders",
"type": "linkedin_search",
"prospectCount": 250,
"createdAt": "2026-05-02T09:30:00.000Z"
}
],
"nextCursor":
To fetch the next page, pass data.nextCursor back as the cursor query parameter:
curl "https://api.sonarly.io/v1/accounts/507f1f77bcf86cd799439011/audiences?limit=10&cursor=aud_01HYR8B9P4D6Y2A7C3E1F0G5H9" \
-H "Authorization: Bearer sk_live_your_api_key_here" \
-H "Accept: application/json"When data.hasMore is false, there are no more pages.
For POST routes, send an Idempotency-Key header so retries do not create duplicate work. The key can be any unique string up to 256 characters and is retained for 24 hours.
curl -X POST https://api.sonarly.io/v1/accounts/507f1f77bcf86cd799439011/prospecting \
-H "Authorization: Bearer sk_live_your_api_key_here" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Idempotency-Key: prospecting-run-2026-05-23-001" \
-d '{
"type": "linkedin_search",
"name": "Berlin Software Engineers",
"searchUrl": "https://www.linkedin.com/search/results/people/?keywords=software%20engineer",
"maxResults": 100,
"searchEmails": false
}'If you retry the same request with the same idempotency key within 24 hours, Sonarly returns the original response instead of starting a duplicate job.
When your key exceeds its request limit, the API returns 429 with RATE_LIMIT_EXCEEDED. Responses include standard rate-limit headers when available:
RateLimit-Limit: 100
RateLimit-Remaining: 0
RateLimit-Reset: 30Back off when RateLimit-Remaining is low, wait at least RateLimit-Reset seconds after a 429, and retry idempotent or idempotency-protected requests first.
Start with Accounts to understand account-group scoping, then choose the section that matches your integration:
| Goal | Next section |
|---|---|
| Read or organize prospect lists | Audiences |
| Import new prospects | Prospecting |
| Read inbox-style messages or queue replies | Messages |
| Create or operate campaigns | Campaigns |
| Read signal scan results | Signals |
| Manage reusable templates |
null| Error body |
| Machine-readable error details |
traceId | Trace ID | Trace ID | Include this when contacting support |
| Templates |