Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintfax.com/docs/llms.txt

Use this file to discover all available pages before exploring further.

Outcome

After this guide you will have a mintfax sandbox integration that does what your Documo client does today: send a fax, list and inspect records, fetch the rendered image, resend, delete, and verify webhook payloads. You will also know which Documo features have no mintfax equivalent and how to keep both providers running side by side until you cut over. Samples are in curl and Node.

Prerequisites

  • A mintfax sandbox API key (prefix mfx_test_, issued at POST /account/register/verify). Sample: mfx_test_4eC39HqLyjWDarjtT1zdp7dc.
  • Your existing Documo API key and a working call to POST https://api.documo.com/v1/fax/send.
  • An HTTPS receiver URL for webhook code.
  • Node 18+ for the Node samples.

What changes at the surface

AreaDocumomintfax
Base URLhttps://api.documo.comhttps://api.mintfax.com/v1
AuthenticationAuthorization: Basic <api_key>Authorization: Bearer mfx_test_... or Bearer mfx_live_...
Send fieldrecipientFax (bare digits)to (E.164 only, leading + and country code)
Cover-page tokensPascalCase: RecipientName, Notes{{snake_case}}: {{recipient_name}}, {{message}}
Webhook securityHTTP Basic auth on the receiverStandard Webhooks: HMAC-SHA256 over {webhook-id}.{webhook-timestamp}.{body} in the webhook-signature header
Each row gets its own step below, plus the behavioral differences that bite during cutover: idempotency, retry budgets, error codes, and the account model.

Step 1: Swap authentication

Documo passes the API key directly after Basic. mintfax uses Bearer tokens with a mfx_test_ or mfx_live_ prefix that routes to sandbox or live. Replace the entire -H 'Authorization: ...' line, not just the value.
# Documo (before)
curl -X POST 'https://api.documo.com/v1/fax/send' \
  -H 'Authorization: Basic YOUR_DOCUMO_KEY' \
  -F 'recipientFax=12125551234' \
  -F 'file=@document.pdf'

# mintfax (after)
curl -X POST 'https://api.mintfax.com/v1/faxes' \
  -H 'Authorization: Bearer mfx_test_4eC39HqLyjWDarjtT1zdp7dc' \
  -F 'to=+12125551234' \
  -F 'file=@document.pdf'
Verify A GET /v1/account with the new header returns 200 and the environment name. 401 unauthenticated means the header value is malformed or the key prefix does not match the environment you expect.

Step 2: Translate the send-fax payload

Field map for the most common parameters:
DocumomintfaxNotes
recipientFaxtoReformat to E.164. Bare digits return validation_failed.
recipientNamerecipient_nameCover-page token value
subjectsubjectSame
notesmessageRename: Documo notes becomes mintfax message
coverPage boolcover_page stringPass standard, hipaa, or none
faxNumbercsidSender CSID transmitted in the T.30 handshake; up to 20 chars
tags arraytags objectUp to 10 keys, 64-char keys, 255-char values
customFields(use tags)Collapse custom fields into the tags map
scheduledOn(no equivalent)mintfax queues immediately; schedule client-side or remove the field
file partfileOne file per request, max 10 MB
mintfax accepts PDF, DOCX, XLSX, JPG, PNG, TIFF, HTML, and TXT. Documo also accepts PPT/PPTX, ODT/ODS/ODP, RTF, GIF, and printer formats (PCL/EPS/PS). Audit upload paths for those types and convert to PDF or DOCX before submitting; unsupported types return 422 validation_failed.
curl -X POST 'https://api.mintfax.com/v1/faxes' \
  -H 'Authorization: Bearer mfx_test_4eC39HqLyjWDarjtT1zdp7dc' \
  -H 'Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000' \
  -F 'to=+12015550100' \
  -F 'file=@invoice.pdf' \
  -F 'cover_page=standard' \
  -F 'recipient_name=Acme Billing' \
  -F 'subject=April invoice' \
  -F 'message=See attached, thanks.' \
  -F 'tags[order_id]=1234'
If you customized Documo’s PascalCase cover-page tokens (RecipientName, SenderName, Pages, Date, Subject, Notes), rename to {{recipient_name}}, {{sender_name}}, {{page_count}}, {{date}}, {{subject}}, {{message}}. RecipientPhone, RecipientCompany, and the domain-logo token have no v1 equivalent; render the cover page yourself and pass it through cover_page_html. Verify The response is 201 with id, status: "queued", the to value, and created_at.

Step 3: Add idempotency to every send

Documo does not advertise an idempotency mechanism. If you retry POST /v1/fax/send after a network timeout, you can double-send. mintfax accepts an Idempotency-Key header on every state-mutating POST. Duplicate keys return the original response without re-processing for 24 hours. Generate one key per logical send and reuse it on retry. mintfax echoes the key in X-Idempotency-Key on the response.
Node
const idempotencyKey = crypto.randomUUID();

for (let attempt = 0; attempt < 3; attempt++) {
  const res = await fetch('https://api.mintfax.com/v1/faxes', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.MINTFAX_KEY}`,
      'Idempotency-Key': idempotencyKey,
    },
    body: form,
  });
  if (res.ok) break;
  if (res.status >= 500) continue; // safe replay with same key
  throw new Error(`fax submit failed: ${res.status}`);
}
Verify Submit the same request twice with the same key. The second response matches the first, no second fax appears in GET /faxes, and X-Idempotency-Key echoes your key. See Idempotency keys.

Step 4: Update list, get, image, resend, and delete

OperationDocumomintfax
List historyGET /v1/faxGET /v1/faxes (cursor-paginated)
Get one faxGET /v1/fax/{messageId}GET /v1/faxes/{id}
Download imageGET /v1/fax/{messageId}/downloadGET /v1/faxes/{id}/image (TIFF)
ResendPOST /v1/fax/{messageId}/resendPOST /v1/faxes/{id}/resend
Delete(portal only)DELETE /v1/faxes/{id} (terminal only)
Pagination is cursor-based: pass meta.next_cursor back as ?cursor=.... Default window is seven days; widen with created_after and created_before. mintfax has no cancel endpoint. Faxes queue immediately and cannot be recalled. If a workflow depends on schedule-then-cancel, redesign before migrating. DELETE /faxes/{id} only works on terminal faxes. In-flight calls return 409 fax_not_terminal with action: wait_for_completion. Documents purged by retention or zero-footprint mode return 422 fax_data_purged from image and resend; submit a new fax. See Errors for the full catalog.

Step 5: Replace webhook Basic auth with Standard Webhooks verification

Documo secures webhooks with HTTP Basic auth on the receiver, optionally pinned to source IP 35.225.187.84. mintfax implements the Standard Webhooks specification: HMAC-SHA256 over {webhook-id}.{webhook-timestamp}.{body}, signed with your endpoint’s secret, with three headers on every delivery (webhook-id, webhook-timestamp, webhook-signature). A receiver that only checks Basic credentials will not auto-port; you have to add verification code. Use the Standard Webhooks reference library for your language - it handles constant-time signature comparison, the 5-minute timestamp window, and parsing rotation tokens. Do not hand-roll the HMAC.
Node
import express from 'express';
import { Webhook } from 'standardwebhooks';

const app = express();
const wh = new Webhook(process.env.MINTFAX_WEBHOOK_SECRET);

app.post(
  '/webhooks/mintfax',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    try {
      const event = wh.verify(req.body, {
        'webhook-id': req.headers['webhook-id'],
        'webhook-timestamp': req.headers['webhook-timestamp'],
        'webhook-signature': req.headers['webhook-signature'],
      });
      // dedupe on event.id (same value as the webhook-id header), then route by event.type
      res.status(200).send('ok');
    } catch {
      res.status(401).send('bad signature');
    }
  }
);
The full multi-language reference (library snippets, raw-body capture, key rotation) is on Verify webhook signatures. Event types differ. Documo fires fax.v1.outbound.init, .succeed, .failed, .complete, .extended. mintfax fires fax.queued, fax.sending, fax.delivered, fax.failed. Map your handler:
Documo eventmintfax event
fax.v1.outbound.initfax.queued
fax.v1.outbound.succeedfax.delivered
fax.v1.outbound.failedfax.failed
fax.v1.outbound.extendedfax.sending - fires once per delivery attempt, so it is also the mid-flight retry signal
fax.v1.outbound.complete(no direct equivalent; treat fax.delivered/fax.failed as terminal)
Payload shape changes: mintfax wraps fields in an envelope (id, type, created, data.object). Use id (evt_-prefixed, also delivered as the webhook-id header) for deduplication and type to route events. The full schema is in Event types. Webhook retry budget shrinks. Documo retries seven times over roughly twenty-seven hours (5s, 25s, 2m, 10m, 52m, 4h, 22h). mintfax delivers up to four attempts on an exponential backoff inside a ~18-minute window before marking the event permanently failed. If your receiver depended on the long Documo backoff, replay the event from the dashboard or refetch via the Events API, or poll GET /faxes/{id} as a fallback. See Webhook delivery and retries for the full schedule. Verify Send a fax to +15005550001 from the sandbox. Your endpoint receives fax.queued then fax.delivered, both with valid signatures. See Sandbox testing.

Step 6: Translate Documo result codes

Documo attaches numeric “Fax Result Codes” to fax records and webhook payloads. mintfax uses string error_code values inside fax.failed events plus an HTTP error envelope on the API itself. Common translations:
Documo codeDocumo meaningmintfax behavior
4100Fax Number Invalid422 validation_failed on submit (E.164 check)
5000Fax Resource Issue500 internal_server_error
6100Fax Number BusyA second fax.sending per retry attempt, then fax.failed with line_busy if retries exhaust
6200Fax Machine Not Answeringfax.failed with a no-answer error_code
6300 / 6500Fax Detection Failedfax.failed with a no-fax-detected error_code
6700Fax Blocked by Recipientfax.failed with a recipient-blocked error_code
6800Fax Negotiation Failedfax.failed with a negotiation-failed error_code
8000-8400Fax Transmit Failedfax.failed with a transmit-failed error_code
9000Fax Failed (terminal)fax.failed with a generic-failure error_code
Switch on the error_code strings from fax.failed payloads rather than hard-coding a translation table. The HTTP error envelope (error, message, action, docs) is in Errors; use action for programmatic next steps.

Account model: where Documo subaccounts do not map

Documo accounts can contain subaccounts, and subaccounts can contain subaccounts, each with their own users, fax numbers, API keys, webhooks, and history. Resellers and multi-tenant SaaS use this for per-customer isolation. mintfax has accounts and one sandbox plus one live environment per account. No multi-level hierarchy. No per-subaccount API key. Translation paths:
  • One Documo account, no subaccounts. Trivial. One mintfax account.
  • Subaccounts for dev/staging/prod separation. Use mfx_test_ for non-production and mfx_live_ for production. Sandbox and live are structurally separate environments under the same account.
  • Subaccounts for per-customer tenancy. No native equivalent. Either run one mintfax account per end-customer (full isolation, including billing) or co-mingle traffic in one account with per-customer namespacing in tags (for example, tags[customer_id]=...) and reconcile in your own database. Webhooks deliver to one URL; you fan out in your code.
  • Reseller / multi-level subaccounts. Not supported. Stay on Documo or build a tenant layer of your own on top of mintfax.
If your Documo integration relied on a child subaccount’s API key for permission scoping, one mintfax key cannot replicate that. Plan for application-side enforcement before cutover.

Cutover and rollback

Run both providers in parallel until you trust the new path. The shape that works:
  1. Generate a sandbox key (mfx_test_ prefix).
  2. Move the receiver code behind a feature flag so a single deploy flips between Documo and mintfax per request.
  3. Mirror traffic for a sample percentage of sends and compare resulting state (status, error code, page count) for one day.
  4. Exercise the failure modes against the magic numbers: +15005550002 (busy), +15005550003 (no answer), +15005550004 (transient, succeeds on retry), +15005550005 (permanent failure), +15005550006 (insufficient balance), +15005550099 (validation failure). See Sandbox testing for the full reference.
  5. Switch reads first (list, get, image), then writes (send, resend, delete), then webhooks. Each switch is its own deploy.
Rollback is the reverse: flip the flag back to Documo and investigate. Because both integrations live behind the same flag, rollback is one config change.

Verify

Migration is complete when:
  • A sandbox fax to +15005550001 returns a fax_-prefixed ID, transitions through queued and submitted, and ends in delivered.
  • Your receiver verifies Standard Webhooks signatures on fax.queued, fax.sending, and fax.delivered via the reference library, deduplicates on the webhook-id header (same value as event.id), and returns 200.
  • A duplicate Idempotency-Key returns the original response without producing a second fax record.
  • An invalid recipient (bare digits, no +) returns 422 validation_failed with context.errors.to.
  • Your error handler reads error_code from fax.failed and error from the HTTP envelope, not Documo’s numeric result codes.

What to do next

  • Verify webhook signatures - Standard Webhooks contract and reference-library snippets beyond Node.
  • Idempotency keys - 24-hour replay window and key generation strategy.
  • Errors - error-code catalog with action hints.
  • Event types - every event type, payload shape, and delivery guarantee.
  • Sandbox testing - magic numbers for simulated success, busy, no-answer, and validation failure.
Last modified on May 14, 2026