Conversations API: Add Inbound Message by Contact ID
The Add Inbound Message endpoint accepts a Contact ID and posts the message to the right thread automatically — no need to resolve a Conversation ID first.
The Add Inbound Message capability lets you post inbound messages into Conversations using a Contact ID, skipping the need to resolve a Conversation ID first. The system either appends to an existing thread or creates a new one, so your integration logic stays simple.
What it does
You provide Contact ID + channel + content. Sparkforge handles thread association.
- If a matching conversation exists on that channel, the message is appended.
- If not, a new conversation is created and returned in the response.
- Works across SMS/MMS, Email, WhatsApp, Messenger, Instagram, and Web Chat.
Why use it
- Fewer API calls — no separate conversation lookup or create step.
- Simpler logic — no branching for "conversation exists vs not."
- Cleaner CRM — messages land in the correct thread automatically.
- Backward compatible — existing "by Conversation ID" patterns still work.
Endpoint and payload
POST /conversations/inbound-messages
Authorization: Bearer <token>
Content-Type: application/jsonRequest (representative)
{
"contactId": "CONTACT_ID",
"channel": "sms | whatsapp | email | messenger | instagram | webchat",
"endpoint": {
"phone": "+15551234567",
"email": "user@example.com"
},
"content": {
"text": "Hello from our provider",
"attachments": [
{
"type": "image|file|video",
"url": "https://example.com/file.jpg",
"filename": "file.jpg",
"sizeBytes": 123456
}
]
},
"metadata": {
"providerMessageId": "ext-abc-123",
"externalThreadKey": "optional-correlation",
"timestamp": "2026-02-04T10:15:30Z"
},
"idempotencyKey": "fd2d5f6f-5a9f-4b0a-8d68-0d5f6a1c9e5a"
}Response (representative)
{
"messageId": "MSG_123",
"conversationId": "CONV_987",
"contactId": "CONTACT_ID",
"channel": "sms",
"direction": "inbound",
"createdAt": "2026-02-04T10:15:31Z"
}Threading rules
- Existing thread, same channel: message is appended.
- No suitable thread: a new conversation is created and returned.
- Multiple endpoints per contact: include the
endpointhint (phone or email) to disambiguate. - Multi-location: ensure the auth context targets the correct location.
- Closed/archived only: a new conversation is created.
Setup checklist
- Confirm Conversations and Contacts API scopes for your role.
- Authenticate with OAuth or API key per your environment.
- Have a reliable way to obtain Contact IDs upstream (phone or email match).
- Verify location context matches the contact's location.
Channel notes
- SMS/MMS: respect character and media size limits; use reachable media URLs.
- WhatsApp: follow template/free-form rules and media specs.
- Email: include proper MIME types; supports text, HTML, and attachments.
- Messenger/Instagram: watch platform rate limits and media specs.
- Web Chat: rich content depends on widget capabilities; fall back to text if needed.
Idempotency and retries
Always send an idempotencyKey. Network timeouts and provider hiccups are normal — keys prevent duplicate posts when you retry.
Frequently Asked Questions
Do I still need the Conversation ID endpoint?
No, but it still works. Use Contact ID for new integrations to skip the conversation lookup step.
What happens if the contact has multiple phone numbers?
Pass the endpoint hint (endpoint.phone or endpoint.email) so the system routes the message to the correct thread.
How do I avoid duplicate messages on retry?
Send an idempotencyKey on every request. The API treats repeated calls with the same key as the same operation.
Can I post inbound messages on any channel?
Yes — SMS/MMS, Email, WhatsApp, Messenger, Instagram, and Web Chat are all supported, subject to each platform's content rules.
What if no conversation exists for the contact?
The API creates a new conversation automatically and returns the conversationId in the response.
Was this article helpful?
Thanks for the feedback.