Vocatech

By area

Media

Read from the API’s own reference file every hour.

Plain text

Short-lived links to message attachments, call recordings and fax documents.

Get a media link

GET/v1/media/{id}

Returns a short-lived link to one file:

  • att_<n>: a message attachment, from GET /v1/messages or a message webhook. A bare number is read as an attachment too.
  • rec_<n>: the recording of one call leg, from recording_url or recordings in GET /v1/calls.
  • fax_<n>: a fax document, from GET /v1/faxes.

url is a signed link, good for 30 minutes (expires_at). Download the file with a plain GET: the signed link needs no key. Ask again for a fresh link.

A call parked and picked up again is recorded in parts. rec_<n> answers the latest part; rec_<n>?part=N answers part N (from 1). The answer names the part it holds (part of parts) with its recording_id and start_time. A part that does not exist answers 404, and the message says how many parts there are.

Two exceptions return a plain link with no expires_at: an attachment on a message you sent (you get back the URL you sent it with), and a picture received in the last few minutes, before its stored copy is ready.

Anything that is not yours answers 404. A key with the messaging scope may fetch attachments only.

Each request is written to your account's HIPAA access log.

Request

curl https://api.vocatech.com/v1/media/rec_48213907 \
  -H "Authorization: Bearer YOUR_API_KEY"

Parameters

NameInTypeDescription
id requiredpathstringatt_<n>, rec_<n> or fax_<n>. Matches ^(att_|rec_|fax_)?[0-9]+$.
partqueryintegerFor a recording (rec_<n>) only. Which part of a recording saved in parts, from 1, oldest first. Leave it out for the latest part. recordings in GET /v1/calls gives each part's link. At least 1. For example 1.

Answers

200
A link to the file.

When type is attachment

FieldTypeDescription
id requiredstringMatches ^att_[0-9]+$.
type requiredstringAlways attachment.
source requiredstringWhere the message came from. One of sms or whatsapp.
content_type requiredstring or null
filename requiredstring or null
size requiredinteger or nullBytes, when known.
url requiredstring (uri)A signed link, good for 30 minutes. For an attachment on a message you sent, the URL you sent it with.
expires_atstring (date-time)When the signed link stops working. Left out when url is not a signed link.

When type is recording

FieldTypeDescription
id requiredstringMatches ^rec_[0-9]+$.
type requiredstringAlways recording.
content_type requiredstringaudio/ and the file's extension, for example audio/mp3 or audio/wav.
format requiredstringThe file's extension, for example mp3.
duration requiredinteger or nullSeconds.
url requiredstring (uri)A signed link, good for 30 minutes.
expires_at requiredstring (date-time)
part requiredintegerWhich part this is, from 1. Without ?part=, the latest part.
parts requiredintegerHow many parts the recording has. Nearly always 1.
recording_id requiredintegerThe recording's id, as in recordings and the call.transcription event.
start_time requiredstring (date-time) or nullWhen this part started. UTC, ISO 8601 with milliseconds.

When type is fax

FieldTypeDescription
id requiredstringMatches ^fax_[0-9]+$.
type requiredstringAlways fax.
content_type requiredstringAlways application/pdf.
format requiredstringAlways pdf.
pages requiredinteger or null
url requiredstring (uri)A signed link, good for 30 minutes.
expires_at requiredstring (date-time)
Message attachment
{
  "id": "att_90211",
  "type": "attachment",
  "source": "sms",
  "content_type": "image/jpeg",
  "filename": "photo-0921.jpg",
  "size": 184233,
  "url": "https://files.example.com/signed/att_90211.jpg?sig=7c2e9a41",
  "expires_at": "2026-09-24T14:35:09.000Z"
}
Call recording (the latest part)
{
  "id": "rec_48213907",
  "type": "recording",
  "content_type": "audio/mp3",
  "format": "mp3",
  "duration": 309,
  "url": "https://files.example.com/signed/rec_48213907.mp3?sig=b71f0c9e",
  "expires_at": "2026-09-24T14:35:09.000Z",
  "part": 2,
  "parts": 2,
  "recording_id": 10577702,
  "start_time": "2026-09-21T14:04:31.000Z"
}
Fax document
{
  "id": "fax_77120",
  "type": "fax",
  "content_type": "application/pdf",
  "format": "pdf",
  "pages": 3,
  "url": "https://files.example.com/signed/fax_77120.pdf?sig=3d5a8c20",
  "expires_at": "2026-09-24T14:35:09.000Z"
}
400
The id is not in a form we know.
Example bodies
Example
{
  "error": {
    "code": 400,
    "type": "BAD_REQUEST",
    "message": "Invalid recording segment ID."
  }
}
Example
{
  "error": {
    "code": 400,
    "type": "BAD_REQUEST",
    "message": "Invalid attachment ID."
  }
}
Example
{
  "error": {
    "code": 400,
    "type": "BAD_REQUEST",
    "message": "Invalid fax ID."
  }
}
Example
{
  "error": {
    "code": 400,
    "type": "BAD_REQUEST",
    "message": "Invalid recording part. Use a whole number from 1."
  }
}
401
No key, or a key that is wrong or turned off.
403
A messaging key asked for a recording or a fax, the account has no call recording set up, or the key's scopes or address.
Example bodies
Messaging key, recording id
{
  "error": {
    "code": 403,
    "type": "FORBIDDEN",
    "message": "This API key is limited to messaging and cannot fetch recording media."
  }
}
No call recording
{
  "error": {
    "code": 403,
    "type": "FORBIDDEN",
    "message": "Company not configured for call recordings."
  }
}
404
Not found, not yours, or not ready yet.
Example bodies
Example
{
  "error": {
    "code": 404,
    "type": "NOT_FOUND",
    "message": "Attachment not found."
  }
}
Example
{
  "error": {
    "code": 404,
    "type": "NOT_FOUND",
    "message": "Recording not found."
  }
}
Example
{
  "error": {
    "code": 404,
    "type": "NOT_FOUND",
    "message": "Recording file not yet available."
  }
}
Example
{
  "error": {
    "code": 404,
    "type": "NOT_FOUND",
    "message": "Recording part not found. This recording has 2 parts."
  }
}
Example
{
  "error": {
    "code": 404,
    "type": "NOT_FOUND",
    "message": "Fax document not found."
  }
}
Example
{
  "error": {
    "code": 404,
    "type": "NOT_FOUND",
    "message": "Fax document not yet available."
  }
}
410
The attachment's file is no longer available.
Example body
Example
{
  "error": {
    "code": 410,
    "type": "ERROR",
    "message": "Media file no longer available."
  }
}
429
A rate limit was reached. Wait Retry-After seconds. The body names the counter, the window and the limit.
HeaderTypeDescription
Retry-AfterintegerSeconds to wait before you try again.
500
Fax documents are not set up on our side.
Example body
Example
{
  "error": {
    "code": 500,
    "type": "SERVER_ERROR",
    "message": "Fax service not configured."
  }
}
503
Our storage refused us. The file exists. Contact support if it lasts. Or the key could not be checked.
HeaderTypeDescription
Retry-AfterintegerSeconds to wait before you try again.
Example body
Example
{
  "error": {
    "code": 503,
    "type": "ERROR",
    "message": "Recording storage access failed on our side. The recording exists. Contact support."
  }
}