Vocatech

By area

Faxes

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

Plain text

Send faxes from your fax lines and read your fax history.

Send a fax

POST/v1/faxes

Sends one fax from one of your fax lines. Send the document as a base64-encoded PDF of at most 25 pages, up to 20 MB before encoding. Another file type, a longer PDF, or a PDF whose pages cannot be read is refused with 400.

Limits. Per account: 3 requests a minute and 50 faxes sent a day (Eastern calendar day). The fax API is for sending your own documents, not for marketing or bulk faxing.

from must be an active fax line on your account. to must be a valid 10-digit US or Canadian number. Premium numbers (900, 976), service codes and area codes that are other countries are refused.

The answer is 201 with a fax_id once the fax carrier has the job. Sending takes minutes. Read the outcome in GET /v1/faxes (status), and fetch the document with GET /v1/media/{fax_id}.

Dry run. test: true runs every check (the numbers, the file and its pages, your line, the monthly limit) and sends nothing. It counts toward the 3 a minute, never toward the 50 a day.

Monthly limit. Each account may send 1,000 fax pages a month for each fax line on it (unless Vocatech set another figure), pooled across its lines, counted by the Eastern calendar month across the API, the portal and email to fax. Past it, the answer is 429. Another fax line brings another 1,000 pages a month; contact Vocatech support for a line or a different figure.

Request

curl -X POST https://api.vocatech.com/v1/faxes \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "7185550100",
    "to": "7185550142",
    "filename": "intake-form.pdf",
    "subject": "Intake form",
    "file": "'"$(base64 < intake-form.pdf | tr -d '\n')"'"
  }'

Body

FieldTypeDescription
from requiredstringOne of your active fax lines, 10 digits. Punctuation and a leading 1 are ignored. For example 7185550100.
to requiredstringThe recipient's fax number: a valid 10-digit US or Canadian number. Premium numbers (900, 976) and area codes that are other countries are refused. For example 7185550142.
file requiredstring (base64)The document as base64. Send a PDF. Up to 20 MB before encoding.
filenamestringThe document's file name. Default document.pdf.
subjectstringA subject for your records. It shows in GET /v1/faxes.
recipient_namestringThe recipient's name, passed to the fax carrier.
testbooleanA dry run: check everything and send nothing. Default false.
Example
{
  "from": "7185550100",
  "to": "7185550142",
  "filename": "intake-form.pdf",
  "subject": "Intake form",
  "recipient_name": "Jordan Reyes",
  "file": "JVBERi0xLjQKJcfsj6IKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c+PgplbmRvYmoK"
}

Answers

200
A dry run passed every check. Nothing was sent.
FieldTypeDescription
status requiredstringAlways test.
fax requiredobject
fax.from requiredstring
fax.to requiredstring
fax.filename requiredstring
fax.fax_line requiredstringThe fax line's name in the portal.
fax.valid requiredbooleanAlways true.
Example
{
  "status": "test",
  "fax": {
    "from": "7185550100",
    "to": "7185550142",
    "filename": "intake-form.pdf",
    "fax_line": "Front Desk Fax",
    "valid": true
  }
}
201
The fax carrier has the job.
FieldTypeDescription
status requiredstringAlways queued.
fax requiredobject
fax.fax_id requiredstringThe fax's id. Use it with GET /v1/media/{id}. Matches ^fax_[0-9]+$.
fax.faxage_job_id requiredstring or nullThe fax carrier's job id.
fax.from requiredstring
fax.to requiredstring
fax.filename requiredstring
fax.subject requiredstring or null
fax.created_at requiredstringWhen we took it, ISO 8601 with the Eastern offset.
Example
{
  "status": "queued",
  "fax": {
    "fax_id": "fax_77120",
    "faxage_job_id": "93125501",
    "from": "7185550100",
    "to": "7185550142",
    "filename": "intake-form.pdf",
    "subject": "Intake form",
    "created_at": "2026-09-24T10:05:09-04:00"
  }
}
400
A missing field, a number that is not 10 digits, a destination we refuse, or a file that is not base64.
Example bodies
Example
{
  "error": {
    "code": 400,
    "type": "BAD_REQUEST",
    "message": "Missing required fields: from, to, and file are required."
  }
}
Example
{
  "error": {
    "code": 400,
    "type": "BAD_REQUEST",
    "message": "Invalid to number format. Expected 10 digits."
  }
}
Example
{
  "error": {
    "code": 400,
    "type": "BAD_REQUEST",
    "message": "to may not be a premium-rate number (900)."
  }
}
Example
{
  "error": {
    "code": 400,
    "type": "BAD_REQUEST",
    "message": "to is outside the US and Canada (area code 876). International numbers are not dialed through the API."
  }
}
Example
{
  "error": {
    "code": 400,
    "type": "BAD_REQUEST",
    "message": "File must be base64-encoded."
  }
}
401
No key, or a key that is wrong or turned off.
403
Refused: faxing is not on for your account, from is not an active fax line of yours, the key's scopes, or the address.
Example bodies
Faxing is off
{
  "error": {
    "code": 403,
    "type": "FORBIDDEN",
    "message": "Faxing is not enabled for this company."
  }
}
Not your fax line
{
  "error": {
    "code": 403,
    "type": "FORBIDDEN",
    "message": "Invalid from number. Must be an active fax line assigned to your company."
  }
}
413
The document is over 20 MB.
Example body
Example
{
  "error": {
    "code": 413,
    "type": "ERROR",
    "message": "The document is too large. The limit is 20 MB."
  }
}
429
The faxes counter is full (3 a minute per account), the account has sent its 50 faxes for the day, or the account's monthly page limit is used. The day and monthly limits answer with an action error and no Retry-After.
HeaderTypeDescription
Retry-AfterintegerSeconds to wait before you try again.
Example body
Example
{
  "error": {
    "code": 429,
    "type": "RATE_LIMIT_EXCEEDED",
    "message": "This account has used its 3,000 outbound fax pages for the month, 1,000 pages for each of its 3 fax lines. Contact Vocatech support to raise it."
  }
}
500
The fax carrier refused the job or could not be reached. The message is the carrier's error, or the connection error.
Example body
Example
{
  "error": {
    "code": 500,
    "type": "SERVER_ERROR",
    "message": "cURL error 28: Operation timed out after 60000 milliseconds with 0 bytes received"
  }
}
503
Try again shortly. The key could not be checked just now (Retry-After: 5), or a service this route needs could not be reached.
HeaderTypeDescription
Retry-AfterintegerSeconds to wait before you try again.

List faxes

GET/v1/faxes

Your sent and received faxes in a date window, newest first.

Dates work as in GET /v1/calls: start_date and end_date together as local days in timezone, or neither for today, at most 366 days. The response echoes the local days you asked for.

Paging. limit is 500 by default and at most 500. Faxes that tie on time keep a stable order.

has_document says whether GET /v1/media/{fax_id} can return the PDF. Answers 403 when faxing is not on for your account.

Known issue. Fax times are stored in Eastern time. sent_at shows that Eastern clock time with a Z, so it reads 4 or 5 hours early, and the date window is compared the same way: a fax from midnight to about 4 AM Eastern lands in the previous day's window.

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

Request

curl -G https://api.vocatech.com/v1/faxes \
  -H "Authorization: Bearer YOUR_API_KEY" \
  --data-urlencode "start_date=2026-09-24" \
  --data-urlencode "end_date=2026-09-24"

Parameters

NameInTypeDescription
start_datequerystring (date)First local day of the window, YYYY-MM-DD, in timezone. Send it with end_date. Send neither for today. A single date is ignored and you get today. For example 2026-09-01.
end_datequerystring (date)Last local day of the window, YYYY-MM-DD, included in full. At most 366 days after start_date. For example 2026-09-07.
timezonequerystringIANA time zone for the dates, for example America/Chicago. An unknown zone falls back to America/New_York. The response echoes the zone used. Default America/New_York.
directionquerystringincoming (received) or outgoing (sent). One of any, incoming or outgoing. Default any.
statusquerystringOnly faxes in this status. One of any, in_progress, completed, failed or restricted. Default any.
searchquerystringText to find in the other party's number or the subject.
sortquerystringOrder by time. Rows that tie keep a stable order, so paging is safe. One of day_desc or day_asc. Default day_desc.
pagequeryintegerPage number, from 1. Default 1. At least 1.
limitqueryintegerRows per page, 1 to 500. A value outside that range is brought inside it. Default 500. From 1 to 500.

Answers

200
The faxes in the window.
FieldTypeDescription
query requiredobjectThe filters that were applied, echoed back.
query.company_idinteger
query.start_datestring (date)
query.end_datestring (date)
query.directionstring
query.statusstring
query.searchstring
query.timezonestring
faxes requiredarray of objects
faxes[].fax_id requiredstringUse it with GET /v1/media/{id} to get the document. Matches ^fax_[0-9]+$.
faxes[].direction requiredstringOne of incoming or outgoing.
faxes[].status requiredstringOne of in_progress, completed, failed, restricted or unknown.
faxes[].from requiredstring or nullDigits without the leading 1.
faxes[].to requiredstring or nullDigits without the leading 1.
faxes[].pages requiredinteger or null
faxes[].subject requiredstring or null
faxes[].faxage_job_id requiredstring or nullThe fax carrier's job id.
faxes[].has_document requiredbooleanTrue when GET /v1/media/{fax_id} can return the PDF.
faxes[].sent_at requiredstring (date-time) or nullWhen the fax was logged. Known issue: this is Eastern time written with a Z, so it reads 4 or 5 hours early.
meta requiredobjectPaging for list routes. Each list adds its own total.
meta.page requiredintegerThis page, from 1.
meta.limit requiredintegerRows per page, after limits were applied.
meta.total_pages requiredintegerHow many pages there are.
meta.total_faxes requiredintegerFaxes that match, across all pages.
Example
{
  "query": {
    "company_id": 1234567890,
    "start_date": "2026-09-24",
    "end_date": "2026-09-24",
    "direction": "any",
    "status": "any",
    "search": "",
    "timezone": "America/New_York"
  },
  "faxes": [
    {
      "fax_id": "fax_77135",
      "direction": "incoming",
      "status": "completed",
      "from": "2125550187",
      "to": "7185550100",
      "pages": 2,
      "subject": null,
      "faxage_job_id": "93125877",
      "has_document": true,
      "sent_at": "2026-09-24T11:40:00.000Z"
    },
    {
      "fax_id": "fax_77120",
      "direction": "outgoing",
      "status": "completed",
      "from": "7185550100",
      "to": "7185550142",
      "pages": 3,
      "subject": "Intake form",
      "faxage_job_id": "93125501",
      "has_document": true,
      "sent_at": "2026-09-24T10:05:09.000Z"
    }
  ],
  "meta": {
    "page": 1,
    "limit": 500,
    "total_pages": 1,
    "total_faxes": 2
  }
}
400
A date that is not YYYY-MM-DD, an end before the start, or a window over 366 days.
Example body
Example
{
  "error": {
    "code": 400,
    "type": "BAD_REQUEST",
    "message": "Invalid date format or timezone."
  }
}
401
No key, or a key that is wrong or turned off.
403
Faxing is not on for your account, or the key's scopes or address.
Example body
Example
{
  "error": {
    "code": 403,
    "type": "FORBIDDEN",
    "message": "Faxing is not enabled for this company."
  }
}
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
An unexpected fault on our side, or a search that ran longer than 30 seconds and was stopped.
503
Try again shortly. The key could not be checked just now (Retry-After: 5), or a service this route needs could not be reached.
HeaderTypeDescription
Retry-AfterintegerSeconds to wait before you try again.