List a Voicegram's messages
Returns the conversation of one Voicegram: every entry saved to it, in time order, with a count and the time and direction of the last one.
Returns the conversation of one Voicegram: every entry saved to it, in time order, with a count and the time and direction of the last one. A Voicegram with no entries returns an empty list.
Every entry carries sender_verification, its reason and a plain sentence, and an entry Voicegram could not confirm the sender of is listed in full like any other.
A removed entry stays in the list with removed_at set and body and subject both null. Its author, recipient_to and recipient_cc stay as they were saved. The list holds at most the 500 most recent entries.
Part of the conversations feature: a workspace it is not available for gets 404 conversation_not_available.
Endpoint
GET /api/v1/voicegrams/{id}/messages
Authentication
Bearer Personal Access Token. See Authentication.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string (uuid) | yes | The Voicegram's identifier (a UUID, as returned by findVoicegramsBySender and shown in data.id of an event). |
Example request
curl https://www.voicegram.io/api/v1/voicegrams/:id/messages \
-H "Authorization: Bearer vg_pat_<your-token>"Responses
The Voicegram's conversation
| Field | Type | Required | Description |
|---|---|---|---|
conversation | object | yes | |
conversation.message_count | integer | yes | |
conversation.last_message_at | string | null | yes | |
conversation.last_direction | string | null | yes | |
messages | array of object | yes | |
messages[].id | string | yes | The entry's own identifier. |
messages[].medium | enum ("email", "sms", "whatsapp", "call", "note") | yes | What kind of entry it is. |
messages[].direction | string | null | yes | outbound is your side speaking to the sender. inbound is the sender, or someone copied in on an email, speaking to you. Null for a note. |
messages[].source | enum ("logged", "forwarded") | yes | logged: recorded as it happened. forwarded: an email a member forwarded to the Voicegram's saving address. For a forwarded entry, sender_verification describes the member who forwarded it (logged_by), not whoever wrote the message inside, which Voicegram cannot check: an automation that reads author.type recorder as "the sender replied" should also require source logged. |
messages[].created_via | enum ("dashboard", "inbound_email", "api") | yes | How the entry reached Voicegram: typed in the dashboard, received at the Voicegram's saving address, or written through this API. |
messages[].author | object | yes | Who said it. recorder is the person who left the Voicegram. workspace is your side: a signed-in member (name is their display name) or an API token (name is null; see logged_by). participant is someone who was copied in on an email and then wrote in under their own address, which also covers an email from an address Voicegram had not seen before that a member reviewed and kept. The recorder's own address is never here: it is in data.sender. |
messages[].author.type | enum ("workspace", "recorder", "participant") | yes | |
messages[].author.name | string | null | yes | A member's display name on a workspace entry. Null on every other entry. |
messages[].author.address | string | null | yes | The address a participant wrote from. Null on every other entry. |
messages[].logged_by | object | null | yes | Who saved the entry, when that is someone other than its author: a member who logged or forwarded it, or the API token that wrote it. Null when there is no one else. |
messages[].sender_verification | enum ("verified", "not_verified") | yes | Whether Voicegram could confirm who sent this entry. Present on every entry, not only emails. not_verified means the email provider could not confirm the email came from the address it claims; the dashboard shows these as "Sender not confirmed". The entry is still saved and delivered in full. The webhooks guide (https://www.voicegram.io/docs/integrations/webhooks) says how to filter on it before an automation acts on a reply. See "Why couldn't Voicegram confirm who sent an email?" (https://www.voicegram.io/docs/workspace/sender-not-confirmed). |
messages[].sender_verification_reason | enum ("sender_domain_authenticated", "sender_domain_not_authenticated", "entered_by_signed_in_member", "entered_with_api_token") | yes | Why the entry has its label. sender_domain_authenticated: an email the provider confirmed. sender_domain_not_authenticated: an email it could not confirm (the only not_verified reason). entered_by_signed_in_member: logged by hand in the dashboard. entered_with_api_token: written through this API. |
messages[].sender_verification_note | string | yes | The same label as one plain-English sentence, derived from sender_verification_reason: "Confirmed by the email provider.", "Entered by a signed-in member.", "Entered with an API token.", or, for not_verified, "The email provider could not confirm this message came from the address it claims. The address may still be genuine, since many small domains have not set up email authentication, but anyone who has this conversation's saving address could also have sent it. Treat it as unconfirmed before automating on it." |
messages[].recipient_to | array | null | yes | The To addresses of an emailed entry, never including the saving address. Null unless the entry is an email Voicegram received at its saving address (created_via inbound_email), so null on an email logged by hand too, and on an email saved before Voicegram kept them. |
messages[].recipient_cc | array | null | yes | The Cc addresses of an emailed entry, never including the saving address. Null unless the entry is an email Voicegram received at its saving address (created_via inbound_email), so null on an email logged by hand too, and on an email saved before Voicegram kept them. |
messages[].subject | string | null | yes | The subject line of an emailed entry. Null unless the entry is an email Voicegram received at its saving address (created_via inbound_email), on an email saved before Voicegram kept it, and on a removed entry. |
messages[].body | string | null | yes | The text of the entry. Null on a removed entry. |
messages[].occurred_at | string (date-time) | yes | When the entry happened. For a logged call or note it is the time given; for an email it is the time of the email. |
messages[].created_at | string (date-time) | yes | When Voicegram saved the entry. |
messages[].attachments | array of object | yes | The attachments of an emailed entry, named but never delivered. Empty for anything else. |
messages[].attachments[].filename | string | yes | |
messages[].attachments[].content_type | string | null | yes | |
messages[].attachments[].size_bytes | integer | null | yes | |
messages[].removed_at | string | null | yes | Set when a member removed the entry. A removed entry keeps its place, its author, its recipients and its time, and loses its text: body and subject are null. |
{
"conversation": {
"message_count": 2,
"last_message_at": "2026-05-13T20:10:00.000Z",
"last_direction": "inbound"
},
"messages": [
{
"id": "55555555-5555-5555-5555-555555555555",
"medium": "call",
"direction": "outbound",
"source": "logged",
"created_via": "api",
"author": {
"type": "workspace",
"name": null,
"address": null
},
"logged_by": {
"type": "api",
"name": "CRM sync"
},
"sender_verification": "verified",
"sender_verification_reason": "entered_with_api_token",
"sender_verification_note": "Entered with an API token.",
"recipient_to": null,
"recipient_cc": null,
"subject": null,
"body": "Called back and left a message.",
"occurred_at": "2026-05-13T19:40:00.000Z",
"created_at": "2026-05-13T19:40:03.000Z",
"removed_at": null,
"attachments": []
},
{
"id": "66666666-6666-6666-6666-666666666666",
"medium": "email",
"direction": "inbound",
"source": "logged",
"created_via": "inbound_email",
"author": {
"type": "recorder",
"name": null,
"address": null
},
"logged_by": null,
"sender_verification": "verified",
"sender_verification_reason": "sender_domain_authenticated",
"sender_verification_note": "Confirmed by the email provider.",
"recipient_to": [
"owner@example.com"
],
"recipient_cc": [],
"subject": "Re: Your voice message",
"body": "Thanks for getting back to me. Tuesday at 10 works, see you then.",
"occurred_at": "2026-05-13T20:10:00.000Z",
"created_at": "2026-05-13T20:10:02.000Z",
"removed_at": null,
"attachments": []
}
]
}
The PAT is missing, malformed, expired, or revoked.
See Errors for the shared error response shape.
PAT is valid but the account is on the free plan.
See Errors for the shared error response shape.
No Voicegram with this id on the PAT's account (not_found), or conversations are not available for the workspace (conversation_not_available).
See Errors for the shared error response shape.