API Documentation
API Documentation
The account activity log answers two different questions in one response:
Use it when the dashboard shows little activity, when a customer reports missing messages, likes, or comments, or before approving repaired content that might otherwise duplicate an existing action.
Future entries are provisional. Scheduling constraints, workflow branches,
replies, fatigue, business hours, and account limits can move or cancel
planned work. Do not report a future scheduled entry as already sent.
The default request returns a bounded operational window covering seven days before and seven days after the request time.
curl "https://api.sonarly.io/v1/accounts/$ACCOUNT_GROUP_ID/activity" \
-H "Authorization: Bearer $SONARLY_API_KEY" \
-H "Accept: application/json"The API key needs activity:read and access to the requested account group.
For repeatable audits, pass explicit ISO 8601 timestamps in UTC:
curl "https://api.sonarly.io/v1/accounts/$ACCOUNT_GROUP_ID/activity?from=2026-07-07T00:00:00.000Z&to=2026-07-14T23:59:59.000Z&limit=100" \
-H "Authorization: Bearer $SONARLY_API_KEY" \
-H "Accept: application/json"from must be earlier than to, and the requested window cannot exceed 14 days. Use several non-overlapping requests for a longer audit.
Unknown query parameters are rejected with 422 VALIDATION_ERROR; misspelled filters are never silently ignored.
| Parameter | Example | Purpose |
|---|---|---|
campaignId | aabbccddee1122334455ca11 | Only one campaign |
leadId | 507f1f77bcf86cd799439072 | Only one prospect lead |
type | direct_message | Only one action type |
state |
Supported action types are invitation, direct_message, inmail, email, like, comment, profile_view, invitation_withdrawal, wait, condition, and sync.
For example, inspect failed direct messages from one campaign:
curl "https://api.sonarly.io/v1/accounts/$ACCOUNT_GROUP_ID/activity?campaignId=$CAMPAIGN_ID&type=direct_message&state=failed&from=2026-07-07T00:00:00.000Z&to=2026-07-14T23:59:59.000Z" \
-H "Authorization: Bearer $SONARLY_API_KEY" \
-H "Accept: application/json"{
"id": "activity_01K0Q8H8T2A6B4C9D3E7F5G1J0",
"displayAt": "2026-07-14T11:47:37.000Z",
"scheduledAt": "2026-07-14T11:45:00.000Z",
"executedAt": "2026-07-14T11:47:37.000Z",
"originalScheduledAt": "2026-07-14T11:45:00.000Z",
"nextScheduledAt": null,
"type": "direct_message",
"state": "sent",
"deliveryState":
The timestamp fields have different meanings:
| Field | Meaning |
|---|---|
displayAt | Normalized timestamp used to place the item in the log |
scheduledAt | Current or final scheduled time when known |
executedAt | Time execution completed or failed; null for future work |
originalScheduledAt | First scheduled time before rescheduling |
nextScheduledAt | Next attempt after a deferral or reschedule |
workflowStepLabel gives the human-readable workflow position, such as Initial DM, Wait 1 day, or Follow-up DM 1. Use workflowInstanceId, leadId, and nodeId when correlating the log with campaign approvals.
The top-level state describes the normalized activity lifecycle:
| State | Interpretation |
|---|---|
queued / scheduled / waiting | Planned work that has not executed |
processing | Execution has started but is not final |
sent / succeeded | The action completed successfully |
failed / rejected | The action did not complete; inspect reasonCode and reason |
For delivery actions, deliveryState narrows the outbound status to queued, scheduled, processing, sent, failed, deferred, or rejected.
Use these checks in customer-facing reports:
provisional: true means the entry is a current plan, not proof of delivery.executedAt plus state: sent or state: succeeded is evidence that Sonarly executed the action successfully.state: failed or state: rejected means no successful delivery is recorded for that activity item.content is the rendered content associated with the activity. Do not treat it as a reusable template.Results are cursor-paginated. When hasMore is true, pass nextCursor unchanged:
curl "https://api.sonarly.io/v1/accounts/$ACCOUNT_GROUP_ID/activity?from=2026-07-07T00:00:00.000Z&to=2026-07-14T23:59:59.000Z&limit=100&cursor=$NEXT_CURSOR" \
-H "Authorization: Bearer $SONARLY_API_KEY" \
-H "Accept: application/json"Stop when hasMore is false. Keep the same window and filters on every page; changing them invalidates the meaning of the cursor.
The response repeats the effective window so an audit can record exactly what was queried:
{
"items": [],
"nextCursor": null,
"hasMore": false,
"window": {
"from": "2026-07-07T00:00:00.000Z",
"to": "2026-07-14T23:59:59.000Z",
"generatedAt": "2026-07-14T12:00:00.000Z"
}
}campaignId, leadId, and workflowInstanceId.reasonCode and reason.nodeId with the workflow graph in the campaign approval guide.| Status | Meaning | What to do |
|---|---|---|
401 UNAUTHORIZED | The API key is missing, invalid, or revoked | Replace the Bearer token |
403 SCOPE_DENIED | The key lacks activity:read or account-group access | Update permissions or choose an accessible account |
422 VALIDATION_ERROR | Invalid ID, timestamp, cursor, state, type, unknown parameter, or a window longer than 14 days | Correct the query |
429 RATE_LIMIT_EXCEEDED |
For the exact request and response schemas, open the endpoint reference for GET /v1/accounts/{accountGroupId}/activity under Accounts.
failed |
| Only one normalized state |
cursor | Value from nextCursor | Continue pagination |
limit | 1–100 | Page size; default is 50 |
deferred / rescheduled | The action moved to a later slot; inspect nextScheduledAt |
skipped / cancelled | The workflow intentionally did not execute the action |
| The request limit was reached |
| Back off and retry after the reset window |
502 UPSTREAM_ERROR | The activity source could not be read | Retry and include traceId if support is needed |