message.comDevelopers

Voicemails Live

Voicemails are recorded when a caller is sent to voicemail (out-of-hours, no available agents, or explicit caller choice). Each voicemail carries its recording URL and transcription status. The text appears after successful processing; pending or failed processing does not mean the recording is missing.

List voicemails

GET/api/v1/voicemailsAuth: Bearer

Not cursor-paginated in the documented convention's sense: cursor here is a plain ISO timestamp (created-before), plus limit (default 50, max 100). Filters: unread (boolean), state (active default, all, new, heard, or done), deptId.

Code samples

cURL
curl 'https://app.message.com/api/v1/voicemails?unread=true' \
  -H 'Authorization: Bearer YOUR_WORKSPACE_JWT'
JavaScript
const res = await fetch('https://app.message.com/api/v1/voicemails?unread=true', {
  headers: { Authorization: 'Bearer ' + token }
});
const { voicemails } = await res.json();
Python
import requests
r = requests.get(
    "https://app.message.com/api/v1/voicemails",
    headers={"Authorization": f"Bearer {token}"},
    params={"unread": "true"},
)
voicemails = r.json()["voicemails"]
Ruby
require "net/http"
require "json"
uri = URI("https://app.message.com/api/v1/voicemails?unread=true")
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
  req = Net::HTTP::Get.new(uri)
  req["Authorization"] = "Bearer #{token}"
  http.request(req)
end
voicemails = JSON.parse(res.body)["voicemails"]
PHP
<?php
$ctx = stream_context_create([
  "http" => ["method" => "GET", "header" => "Authorization: Bearer $token"]
]);
$voicemails = json_decode(file_get_contents("https://app.message.com/api/v1/voicemails?unread=true", false, $ctx), true)["voicemails"];

Voicemail shape

There is no GET-by-ID; find the one you want in the list response.

Voicemail
{
  "id": "uuid",
  "conversationId": "uuid",
  "phoneNumberId": "uuid",
  "fromE164": "+14155550100",
  "recordingDurationMs": 22300,
  "recordingUrl": "https://cdn.message.com/voicemails/...mp3",
  "transcription": "Hi, this is Jane. I had a question about my order...",
  "transcriptionStatus": "completed",
  "state": "new",
  "listenedAt": null,
  "createdAt": "2026-05-13T15:30:00Z"
}

Lifecycle: listened, done, reopen

PATCH/api/v1/voicemails/:id/listenedAuth: Bearer
PATCH/api/v1/voicemails/:id/doneAuth: Bearer
PATCH/api/v1/voicemails/:id/reopenAuth: Bearer

There is no read/unread toggle. The real lifecycle has three states (new -> heard -> done) and three one-way actions, all idempotent, no body:

  • listened: stamps listenedAt/listenedByAgentId. Flips new to heard; never touches done.
  • done: stamps doneAt/doneByAgentId and sets state: "done", removing it from the active list. On a shared department box this resolves it for the whole team.
  • reopen: only acts on a done row, returning it to heard and clearing the done stamps. No-op on anything else.

Re-trigger transcription

POST/api/v1/voicemails/:id/transcribeAuth: Bearer

An authenticated agent with phone access can retry transcription only for a voicemail visible to their department or extension scope. HTTP 202 means processing started; read transcriptionStatus from the list for the result. There is no delete endpoint for a voicemail; this is the only mutation beyond the lifecycle actions above.

Errors

CodeWhen
400 invalid_queryList query params failed validation.
403 dept_forbiddendeptId filter is outside the agent's department scope.
403 voicemail_forbiddenThe voicemail is outside the agent's permitted mailbox scope.
404 not_foundVoicemail does not exist in this workspace.

Common pitfalls

  • Looking for a delete endpoint. There isn't one. Use done to resolve a voicemail instead of trying to remove it.
  • Looking for read/unread. The real actions are listened, done, and reopen, a three-state lifecycle, not a boolean.
  • Forgetting the conversation link. A voicemail can link to a call conversation, but conversationId may be null. Use the caller’s number and your authorized callback workflow. Posting a text to a call conversation does not place a call or send an SMS.