List recent completed Voicegrams
Returns the N most-recent completed Voicegrams for the PAT's account, in the canonical `voicegram.completed` payload shape.
Returns the N most-recent completed Voicegrams for the PAT's account, in the canonical voicegram.completed payload shape.
Accounts with no completed Voicegrams receive a single sample row (clearly marked).
Endpoint
http
GET /api/v1/voicegrams/recent
Authentication
Bearer Personal Access Token. See Authentication.
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | no | How many Voicegrams to return. Defaults to 3. Values outside the allowed range are clamped to the nearest valid value; non-integer or unparseable input falls back to the default. |
Example request
curl "https://www.voicegram.io/api/v1/voicegrams/recent?limit=3" \
-H "Authorization: Bearer vg_pat_<your-token>"Responses
200OK
Recent Voicegrams in webhook-payload shape
| Field | Type | Required | Description |
|---|---|---|---|
voicegrams | array of object | yes | |
voicegrams[].event | enum ("voicegram.completed") | yes | |
voicegrams[].event_id | string | yes | Stable event identifier of the form evt_<uuid>. The SAME value is sent across retries of the same event. Customers requiring exactly-once delivery should deduplicate on this field. |
voicegrams[].delivered_at | string (date-time) | yes | ISO 8601 timestamp when this delivery attempt fired. |
voicegrams[].data | object | yes | |
voicegrams[].data.id | string | yes | Voicegram row identifier. |
voicegrams[].data.created_at | string (date-time) | yes | |
voicegrams[].data.completed_at | string (date-time) | yes | |
voicegrams[].data.duration_seconds | number | yes | Audio duration in seconds. |
voicegrams[].data.sender | object | yes | |
voicegrams[].data.sender.verification_method | enum ("email", "sms", "whatsapp") | yes | The channel the sender used to give their contact information (email, sms or whatsapp). Whether it was confirmed is in contact_verified. The name predates optional verification and is kept so existing integrations keep working. |
voicegrams[].data.sender.contact_verified | boolean | yes | true when the sender proved they own this email address or phone number by entering a one-time code before recording. false when the verification code was turned off for the widget or campaign: the email or phone is exactly what the sender typed and was never confirmed, so it may be mistyped or belong to someone else. |
voicegrams[].data.sender.email | string | null | yes | Populated when verification_method=email, null otherwise. Exactly one of email, phone, and whatsapp is populated. |
voicegrams[].data.sender.phone | string | null | yes | E.164 number, populated when verification_method=sms, null otherwise. Exactly one of email, phone, and whatsapp is populated. |
voicegrams[].data.sender.whatsapp | string | null | yes | E.164 number, populated when verification_method=whatsapp, null otherwise. Exactly one of email, phone, and whatsapp is populated. |
voicegrams[].data.channel | object | yes | |
voicegrams[].data.channel.type | enum ("domain", "campaign") | yes | |
voicegrams[].data.channel.id | string | yes | |
voicegrams[].data.channel.name | string | yes | |
voicegrams[].data.channel.page_url | string | null | yes | Page URL where the Voicegram was recorded. Null for campaign-sourced Voicegrams. |
voicegrams[].data.transcript | object | yes | |
voicegrams[].data.transcript.text | string | yes | Full transcript text. |
voicegrams[].data.transcript.confidence | number | yes | Transcription confidence score, 0.0 to 1.0. |
voicegrams[].data.summary | object | yes | Structured AI summary object. Groups urgency, sentiment, intent, callback_required, action items, and extracted entities. |
voicegrams[].data.summary.text | string | yes | AI-generated prose summary (max ~200 words). |
voicegrams[].data.summary.urgency | string | null | yes | AI-classified urgency. Null when not classified. |
voicegrams[].data.summary.sentiment | string | null | yes | AI-classified overall sentiment. |
voicegrams[].data.summary.intent | string | null | yes | AI-classified intent (free-form, e.g. inquiry, support, complaint, scheduling, follow-up, sales). |
voicegrams[].data.summary.callback_required | boolean | yes | True when the caller explicitly requested a callback. |
voicegrams[].data.summary.action_items | array of object | yes | AI-extracted action items, normalized to objects with task, priority, and deadline. |
voicegrams[].data.summary.action_items[].task | string | yes | |
voicegrams[].data.summary.action_items[].priority | enum ("low", "medium", "high") | yes | |
voicegrams[].data.summary.action_items[].deadline | string | null | yes | Free-form deadline (e.g. ASAP, by Friday). |
voicegrams[].data.summary.mentioned | object | yes | AI-extracted entities mentioned in the call. |
voicegrams[].data.summary.mentioned.names | array of string | yes | People or companies mentioned by name. |
voicegrams[].data.summary.mentioned.phones | array of string | yes | Phone numbers in E.164 format (+CCNNNNNNNNNN). |
voicegrams[].data.summary.mentioned.emails | array of string | yes | Email addresses. |
voicegrams[].data.audio | object | yes | |
voicegrams[].data.audio.url | string (uri) | yes | Signed listen URL backed by a per-recipient listener token. Validity is plan-scaled: 30 days (Free), 90 days (Starter), 365 days (Pro / Business / Enterprise). After expiry or revocation, the URL returns 403. If the underlying audio file has been deleted (plan retention reached), the URL returns 410. For permanent access, use the auth-gated dashboard_url or re-fetch the Voicegram via this API to receive a fresh URL. |
voicegrams[].data.audio.expires_at | string (date-time) | yes | ISO 8601 timestamp at which url stops working. |
voicegrams[].data.audio.content_type | enum ("audio/webm") | yes | MIME type of the audio at url. Literal audio/webm in v1. |
voicegrams[].data.dashboard_url | string (uri) | yes | Permanent (auth-gated) link to the Voicegram in the Voicegram dashboard. |
voicegrams[].data.tags | array of string | yes | User-supplied tags from the dashboard Tags input. Distinct from the AI-derived summary.urgency / .sentiment / .intent fields. Empty array when the user has not tagged the Voicegram. |
voicegrams[].data.google_review | object | yes | The Google review step for this Voicegram: whether it was on, the review link, and the text the sender was offered. Always present. It records the step as it was when the Voicegram was processed, and webhooks and GET /api/v1/voicegrams/recent report the same saved values, so changing a widget's or campaign's location later does not change them. Voicegrams processed before this field was added report enabled: false with both values null, even if the sender was offered a review. What the sender did next (copied the text, opened Google) happens after this event and is not included; it shows in the message's activity in your dashboard. |
voicegrams[].data.google_review.enabled | boolean | yes | true when the Google review step was on for the widget or campaign this Voicegram came from when it was processed: a Google review location was chosen for it and your plan included Google reviews. false otherwise, and then review_url and draft_text are both null. |
voicegrams[].data.google_review.review_url | string | null | yes | The Google review link the sender was offered for that location. Always set when enabled is true, null when it is false. |
voicegrams[].data.google_review.draft_text | string | null | yes | The review text the sender was offered: their own message as transcribed, with card numbers and Social Security numbers spoken aloud masked, and a very long message shortened to 4,096 characters. The sender can edit it before posting, so a posted review may differ. Null when enabled is false or when the recording had no detected speech. |
json
{
"voicegrams": [
{
"event": "voicegram.completed",
"event_id": "evt_sample-12345678",
"delivered_at": "2026-05-14T19:23:45.000Z",
"data": {
"id": "vg_sample_12345678",
"created_at": "2026-05-13T19:22:00.000Z",
"completed_at": "2026-05-13T19:23:00.000Z",
"duration_seconds": 47,
"sender": {
"verification_method": "email",
"contact_verified": true,
"email": "sample.customer@example.com",
"phone": null,
"whatsapp": null
},
"channel": {
"type": "domain",
"id": "sample-domain-id",
"name": "example.com",
"page_url": "https://example.com/pricing"
},
"transcript": {
"text": "Hi, I wanted to ask about your enterprise pricing options. Please call me back at four one five, five five five, oh one two three or email pricing.questions@example.com. Thanks.",
"confidence": 0.94
},
"summary": {
"text": "Customer asking about enterprise pricing. Wants a callback or follow-up email.",
"urgency": "medium",
"sentiment": "neutral",
"intent": "inquiry",
"callback_required": true,
"action_items": [
{
"task": "Send enterprise pricing details",
"priority": "medium",
"deadline": null
},
{
"task": "Call back at +14155550123",
"priority": "medium",
"deadline": null
}
],
"mentioned": {
"names": [
"Example Corp"
],
"phones": [
"+14155550123"
],
"emails": [
"pricing.questions@example.com"
]
}
},
"audio": {
"url": "https://www.voicegram.io/api/listen/vg_sample_12345678?t=sample-token-redacted",
"expires_at": "2026-05-15T19:23:45.000Z",
"content_type": "audio/webm"
},
"dashboard_url": "https://voicegram.io/dashboard/inbox/vg_sample_12345678",
"tags": [
"pricing",
"enterprise"
],
"google_review": {
"enabled": true,
"review_url": "https://search.google.com/local/writereview?placeid=sample-place-id-12345678",
"draft_text": "Hi, I wanted to ask about your enterprise pricing options. Please call me back at four one five, five five five, oh one two three or email pricing.questions@example.com. Thanks."
}
}
},
{
"event": "voicegram.completed",
"event_id": "evt_sample-87654321",
"delivered_at": "2026-05-14T20:10:00.000Z",
"data": {
"id": "vg_sample_87654321",
"created_at": "2026-05-14T20:08:30.000Z",
"completed_at": "2026-05-14T20:09:15.000Z",
"duration_seconds": 22,
"sender": {
"verification_method": "sms",
"contact_verified": true,
"email": null,
"phone": "+12125550148",
"whatsapp": null
},
"channel": {
"type": "domain",
"id": "sample-domain-id",
"name": "example.com",
"page_url": "https://example.com/contact"
},
"transcript": {
"text": "Hi, it is Jordan. My order has not arrived yet and I need it by Friday. Could someone call me back? Thanks.",
"confidence": 0.97
},
"summary": {
"text": "Jordan reports a late order needed by Friday and requests a callback. The callback number is the verified sender phone.",
"urgency": "high",
"sentiment": "frustrated",
"intent": "support",
"callback_required": true,
"action_items": [
{
"task": "Call Jordan back about the late order",
"priority": "high",
"deadline": null
}
],
"mentioned": {
"names": [
"Jordan"
],
"phones": [],
"emails": []
}
},
"audio": {
"url": "https://www.voicegram.io/api/listen/vg_sample_87654321?t=sample-token-redacted",
"expires_at": "2026-05-16T20:10:00.000Z",
"content_type": "audio/webm"
},
"dashboard_url": "https://voicegram.io/dashboard/inbox/vg_sample_87654321",
"tags": [
"order",
"callback"
],
"google_review": {
"enabled": false,
"review_url": null,
"draft_text": null
}
}
},
{
"event": "voicegram.completed",
"event_id": "evt_sample-24681357",
"delivered_at": "2026-05-15T09:05:00.000Z",
"data": {
"id": "vg_sample_24681357",
"created_at": "2026-05-15T09:03:10.000Z",
"completed_at": "2026-05-15T09:04:20.000Z",
"duration_seconds": 31,
"sender": {
"verification_method": "email",
"contact_verified": false,
"email": "sam.rivera@example.com",
"phone": null,
"whatsapp": null
},
"channel": {
"type": "campaign",
"id": "sample-campaign-id",
"name": "Spring Open House",
"page_url": null
},
"transcript": {
"text": "Hi, this is Sam. I would like to book a visit for Saturday morning if you still have openings. Email me back. Thanks.",
"confidence": 0.95
},
"summary": {
"text": "Sam wants to book a Saturday morning visit and asks for a reply by email.",
"urgency": "medium",
"sentiment": "positive",
"intent": "scheduling",
"callback_required": false,
"action_items": [
{
"task": "Reply to Sam about Saturday morning openings",
"priority": "medium",
"deadline": null
}
],
"mentioned": {
"names": [
"Sam"
],
"phones": [],
"emails": []
}
},
"audio": {
"url": "https://www.voicegram.io/api/listen/vg_sample_24681357?t=sample-token-redacted",
"expires_at": "2026-05-16T09:05:00.000Z",
"content_type": "audio/webm"
},
"dashboard_url": "https://voicegram.io/dashboard/inbox/vg_sample_24681357",
"tags": [
"visit"
],
"google_review": {
"enabled": true,
"review_url": "https://search.google.com/local/writereview?placeid=sample-place-id-24681357",
"draft_text": "Hi, this is Sam. I would like to book a visit for Saturday morning if you still have openings. Email me back. Thanks."
}
}
}
]
}
401Unauthorized
The PAT is missing, malformed, expired, or revoked.
See Errors for the shared error response shape.
403Forbidden
PAT is valid but the account is on the free plan.
See Errors for the shared error response shape.
Need help? Email support@voicegram.io.