API Reference
Queue a scheduled message response
Queues a one-off response through Sonarly's outbound scheduler instead of sending synchronously. The response includes `activityId`, which matches the stable item ID returned by GET /activity for status monitoring. This endpoint only creates scheduled direct-message or InMail replies; it does not edit campaign-generated content, create LinkedIn comments, or send connection-request notes. Pass channel explicitly. Every reply to an existing conversation must use channel=direct_message with the conversationId returned by GET /messages, even when the conversation originally started as InMail; this keeps the response in the existing thread. For an existing prospect, pass prospectId. To answer an inbound-first conversation whose sender is not yet a Sonarly prospect, pass channel=direct_message and conversationId; Sonarly verifies that the conversation belongs to the requested account before scheduling the reply. InMail starts a new conversation and therefore must not include conversationId; it always requires prospectId, channel=inmail, and a subject. When channel is omitted but subject is present, Sonarly treats the response as InMail. The scheduler does not apply a recipient cooldown to replies: when no active outbound request already exists for the same prospect or conversation, Sonarly schedules the next available slot that satisfies business hours, fatigue, daily or weekly limits, and account rate limits. If that first valid slot is more than 72 hours away, the API returns 422 and no message content is queued. Campaign workflow sends continue to use campaign message hours. To edit generated campaign messages, comments, or invite notes, PATCH the campaign workflow-run messages before approval.
/v1/accounts/{accountGroupId}/messages/responsesChannel behavior
Use direct_message when the prospect is connected and has an existing chat. Use inmail with a subject for eligible new conversations.
Not campaign content
This endpoint does not edit campaign-generated messages, create LinkedIn comments, or send connection-request invite notes. For campaign content changes, PATCH workflow-run messages under Campaigns, then approve the run.
Scheduling rules
Replies do not have a recipient cooldown. Sonarly blocks only when the same prospect already has an active outbound request, then otherwise schedules the next valid business-hours slot that passes fatigue, daily or weekly limits, and account rate limits. If the first valid slot is more than 72 hours away, the API returns 422 and does not queue the content.
Safe retries
Send an Idempotency-Key header when retrying. Same-key, same-body retries return the original scheduled request; conflicting retries return 409 IDEMPOTENCY_CONFLICT.
Integration notes
Required API permission
messages:write.
Prerequisites
integration_api_key, account_group_access.
Idempotency
send a stable Idempotency-Key header when retrying this request.
Parameters
accountGroupIdPathType: string
Account group ID that scopes the request.
Required
Idempotency-KeyHeaderType: string
Request field for idempotency key.
Required
Request body
Required
Optional
Content types
application/json
Schema
object
Fields
prospectIdType: string
Sonarly prospect ID scoped to the account group.
Optional
messageType: string
Message body for a scheduled response or editable campaign content item.
Required
channelType: direct_message | inmail
Delivery channel for the response, such as direct_message or inmail.
Optional
conversationIdType: string
Existing conversation ID used when responding in a direct message thread.
Optional
subjectType: string
InMail subject line. Required when channel is inmail.
Optional
Responses
Queued or scheduled outbound message response
Schema: ScheduledMessageResponseSuccessResponse
Request validation failed
Schema: ValidationErrorResponse
Invalid or missing API key
Schema: ErrorResponse
Missing required permission
Schema: ErrorResponse
Conflict — resource is in a state that prevents this operation
Schema: ErrorResponse
Request validation failed
Schema: ValidationErrorResponse
Rate limit exceeded
Schema: ErrorResponse
Internal server error
Schema: ErrorResponse
Upstream service error
Schema: ErrorResponse
Response examples
202 Example JSONScheduledMessageResponseSuccessResponse
{
"success": true,
"data": {
"id": "507f1f77bcf86cd799439011",
"activityId": "507f1f77bcf86cd799439011",
"status": "queued",
"scheduledAt": "2026-04-28T15:30:00.000Z",
"sentAt": "2026-04-28T15:30:00.000Z",
"channel": "direct_message",
"conversationId": "507f1f77bcf86cd799439011",
"messageId": "507f1f77bcf86cd799439011",
"idempotencyKey": "string",
"deferred": true
},
"error": null,
"traceId": "507f1f77bcf86cd799439011"
}400 Example JSONValidationErrorResponse
{
"success": false,
"data": null,
"error": {
"code": "VALIDATION_ERROR",
"message": "Thanks for the context. I can send over details this afternoon.",
"details": "string"
},
"traceId": "507f1f77bcf86cd799439011"
}401 Example JSONErrorResponse
{
"success": false,
"data": null,
"error": {
"code": "string",
"message": "Thanks for the context. I can send over details this afternoon.",
"details": "string"
},
"traceId": "507f1f77bcf86cd799439011"
}403 Example JSONErrorResponse
{
"success": false,
"data": null,
"error": {
"code": "string",
"message": "Thanks for the context. I can send over details this afternoon.",
"details": "string"
},
"traceId": "507f1f77bcf86cd799439011"
}409 Example JSONErrorResponse
{
"success": false,
"data": null,
"error": {
"code": "string",
"message": "Thanks for the context. I can send over details this afternoon.",
"details": "string"
},
"traceId": "507f1f77bcf86cd799439011"
}422 Example JSONValidationErrorResponse
{
"success": false,
"data": null,
"error": {
"code": "VALIDATION_ERROR",
"message": "Thanks for the context. I can send over details this afternoon.",
"details": "string"
},
"traceId": "507f1f77bcf86cd799439011"
}429 Example JSONErrorResponse
{
"success": false,
"data": null,
"error": {
"code": "string",
"message": "Thanks for the context. I can send over details this afternoon.",
"details": "string"
},
"traceId": "507f1f77bcf86cd799439011"
}500 Example JSONErrorResponse
{
"success": false,
"data": null,
"error": {
"code": "string",
"message": "Thanks for the context. I can send over details this afternoon.",
"details": "string"
},
"traceId": "507f1f77bcf86cd799439011"
}502 Example JSONErrorResponse
{
"success": false,
"data": null,
"error": {
"code": "string",
"message": "Thanks for the context. I can send over details this afternoon.",
"details": "string"
},
"traceId": "507f1f77bcf86cd799439011"
}