Outcome
You finish this guide with a mintfax sandbox integration that does what your Dropbox Fax API v3 client does today: send a fax, list and inspect records, fetch the file, and delete on the outbound side. You also add three capabilities the Dropbox Fax API v3 does not document: anIdempotency-Key header on every send, a per-fax max_attempts retry policy, and a defined rate_limit_exceeded error you can back off on. Webhook verification moves from the custom event_hash scheme to Standard Webhooks HMAC-SHA256. Samples are in curl and Node.
Audience and preflight
You are on the Dropbox Fax API v3, callinghttps://api.hellosign.com/v3/fax/send, authenticating with an API key over HTTP Basic or with an OAuth-issued Bearer access token, and receiving webhook deliveries at a URL you registered on the Dropbox Sign API settings page. If you are still on the v1 endpoints, the endpoints below still target the same mintfax surface; you skip the internal v1-to-v3 migration entirely.
Three preflight differences to know before you write any code:
- No monthly minimum. mintfax has no monthly minimum, no per-line fee, and no setup fee. The Dropbox Fax API’s published pricing includes a 100 minimum, and it scales with actual usage.
- One public per-page price. mintfax charges $0.07 per page to every destination, with no volume tiers. The price is on mintfax.com/pricing; high-volume inquiries go to
sales@mintfax.com. The Dropbox Fax API’s per-page price lives on a Dropbox help article and is not linked from the Dropbox Sign API product page. - Single stable API version. mintfax has one version,
/v1. There is no v2, no in-flight migration, and no plan tier that gates a subset of endpoints.
Prerequisites
- A mintfax sandbox API key (prefix
mfx_test_). Two calls provision one:POST /account/registerthenPOST /account/register/verifywith the 6-digit code. Sample:mfx_test_4eC39HqLyjWDarjtT1zdp7dc. - Your existing Dropbox Fax API v3 code and a working call to
POST https://api.hellosign.com/v3/fax/send. - An HTTPS receiver URL for webhook deliveries. The signing secret (prefix
whsec_) is shown once at endpoint creation in the mintfax dashboard; store it asMINTFAX_WEBHOOK_SECRET. - Node 18+ for the Node samples.
Endpoint mapping
Every Dropbox Fax API v3 operation maps to a mintfax endpoint on the outbound side. Inbound has no mintfax equivalent; see step 8 below.
Two differences carry through every row: the base URL changes from
https://api.hellosign.com/v3 to https://api.mintfax.com/v1, and the auth header changes shape. Step 1 covers auth; step 2 covers the send payload.
GET /v1/faxes is cursor-paginated: pass meta.next_cursor back as ?cursor=.... Default window is the last seven days; widen with created_after and created_before. DELETE /v1/faxes/{id} works only on terminal faxes (delivered or failed); in-flight calls return 409 fax_not_terminal.
Step 1: Swap authentication
The Dropbox Fax API v3 accepts either HTTP Basic with the API key (-u "${API_KEY}:") or Bearer with an OAuth access token. A test_mode boolean on the request marks a send as a test, not a separate key.
mintfax accepts one scheme: Bearer with a prefixed key. The prefix names the environment. mfx_test_ routes to sandbox, mfx_live_ routes to live, and mfx_acct_ is an account-scoped administrative key that cannot send faxes. A leaked test key cannot reach a live destination; there is no test_mode request field.
GET https://api.mintfax.com/v1/account with the new header returns 200. A 401 means the header value is malformed or the key prefix does not match the environment you expect; see unauthenticated and api_key_invalid.
Step 2: Translate the send-fax payload
Rename the send-request fields. The Dropbox Fax API’srecipient becomes mintfax’s to (E.164, leading + and country code required); the multipart file part is renamed from files[] to file (one file per request, max 10 MB); the test_mode boolean is dropped because the sandbox key already routes to sandbox.
curl
201 with id (prefix fax_), status: "queued", the to value, and created_at. Bare-digit numbers return 422 validation_failed with context.errors.to.
Step 3: Replace the webhook signature check
The Dropbox Fax API v3 signs every webhook delivery with a homegrown HMAC-SHA256 scheme that hashes the concatenationevent_time + event_type, keyed by the API key, and delivers the hex digest inside the payload as event_hash. The signed input does not include the request body: two different deliveries with the same event_time and event_type share a signature.
mintfax implements the Standard Webhooks specification. Every delivery carries three headers (webhook-id, webhook-timestamp, webhook-signature) and the signed input is {webhook-id}.{webhook-timestamp}.{body}. The signing secret is per endpoint, prefixed whsec_, and shown once at creation. Receivers reject signatures whose timestamp is more than 5 minutes off the receiver’s clock.
Use the Standard Webhooks reference library for your language. It handles constant-time signature comparison, the timestamp window, and multi-secret rotation.
Node
event_type and the receiver branches on that value. mintfax fires fax.queued, fax.sending, fax.delivered, and fax.failed, with fax.sending firing once per delivery attempt. Route on event.type, dedupe on event.id (echoed in the webhook-id header). Full schema at Event types; the complete verification recipe including key rotation is at Verify webhook signatures.
Verify Send a fax to +15005550001 from the sandbox. Your endpoint receives fax.queued then fax.delivered, both with valid Standard Webhooks signatures.
Step 4: Add idempotency to every send
The Dropbox Fax API v3 does not document anIdempotency-Key header on POST /v3/fax/send, an equivalent replay-safety token in the request body, or a duplicate-detection field on the response. A retry after a network timeout can double-send.
mintfax accepts Idempotency-Key on POST /v1/faxes. Duplicate keys return the original response without re-processing for 24 hours. A request without the header receives an X-Idempotency-Key: not provided; recommended nudge header on the response. Generate one key per logical send and reuse it on retry.
Node
- Same key with a different body returns
409 idempotency_key_reuse. Either regenerate the key or replay the exact same body. - Same key while the original is still in flight returns
409 idempotency_key_in_progress. Wait and re-pollGET /v1/faxes/{id}instead of resubmitting.
Idempotent-Replayed: true. Full behaviour on Idempotency keys.
Verify Submit the same request twice with the same key. The second response matches the first, no second fax appears in GET /v1/faxes, and the response header echoes the key.
Step 5: Set a per-fax retry policy
The Dropbox Fax API v3 does not document a per-fax retry policy: there is nomax_attempts, retry_count, or equivalent field in the send-request body, and the reference does not state what happens when a transmission fails on the carrier side. A busy signal may be retried, or it may not; the docs do not say.
mintfax retries carrier failures automatically. The default is 3 attempts with backoff 1m / 3m / 5m / 5m between attempts. Set max_attempts in the range 1-5 per fax to override.
curl
busy, no_answer, line_quality, carrier_busy, network_error, timeout, internal_error) consume an attempt. Terminal codes (invalid_number, bad_destination, no_route) short-circuit to fax.failed regardless of attempts remaining. Full lifecycle on the fax resource’s attempts[] array; a fax.sending event fires once per attempt.
Verify Send to +15005550004 (the DelayedDelivery sandbox number). The first attempt fails with a transient error, then attempt 2 succeeds. You receive two fax.sending events and one fax.delivered.
Step 6: Handle 429 rate-limit responses
The Dropbox Fax API v3 enforces a hard cap of 200 pending faxes per user per day. Exceeding the cap returns HTTP 429 with the body “Please wait. You already have at least 200 transmissions that are currently pending or transmitting.” The Dropbox help article for the rate limit does not document aRetry-After header or a programmatic wait-time hint on that response, so the client picks its own backoff.
mintfax returns HTTP 429 with rate_limit_exceeded in the error envelope. Back off before retrying and reuse the same Idempotency-Key on the resend so the retry is safe.
Node
error: "rate_limit_exceeded" and request_id: "req_...". See Errors for the envelope.
Step 7: Move from test_mode to the sandbox environment
The Dropbox Fax API v3 marks a send as a test by setting test_mode: true on the request. Live and test traffic share the same key and the same endpoint; the boolean decides which is which.
mintfax separates environments by key prefix. mfx_test_ keys route to the sandbox and cannot reach a live destination. Nine test numbers force nine outcomes:
Any non-magic sandbox number defaults to the Delivered outcome. Sandbox and live share the same API surface; three behaviours differ (credit top-ups, PSTN routing, and the live-activation gate). See Sandbox testing for the full matrix.
Step 8: Inbound gap
mintfax is outbound only in v1. There is no inbound receive capability, no inbound-fax storage, and no inbound-fax API. If your workload depends on receiving faxes to a provisioned number, or on managing an inbox through a portal, the Dropbox Fax API is the right tool for now and mintfax is not a drop-in. One operational note on the Dropbox side worth carrying with you either way: received faxes cannot be deleted through the Dropbox Fax API. To delete a received fax, a user has to log in to the web application. If a HIPAA-shaped workflow requires API-driven PHI deletion on inbound records, that constraint on the Dropbox Fax API is a live retention consideration independent of the choice to migrate. For outbound-only workloads, continue to step 9.Step 9: Signup and agreements
The Dropbox Fax API’s signup path routes through the Dropbox Sign Support team. To move from evaluation to a working API key, a would-be customer emailssupport@hellosign.com and sets up the API after that. Supporting HIPAA compliance on any Dropbox Sign product requires an annual Standard or Premium plan, a signed Business Associate Agreement, and a minimum contract value that Dropbox does not publish.
mintfax’s signup is self-serve through the API. POST /account/register followed by POST /account/register/verify with a 6-digit code provisions a sandbox key immediately. No card, no BAA, no support ticket. Live activation happens on the first successful live credit purchase.
The BAA and DPA are separate click-through documents in the dashboard. Acceptance writes a durable evidence record (account, template version, signer name and title, IP, user agent, accepted_at) and the executed PDF is downloadable immediately. No sales contact, no annual plan gate.
Migration checklist
Work through these in order. Each item corresponds to a step above.- Sandbox key issued from
POST /account/register/verify. - Base URL updated to
https://api.mintfax.com/v1. - Auth header changed from HTTP Basic (or Bearer OAuth) to
Authorization: Bearer mfx_test_.... -
test_mode: trueremoved from the send payload; sandbox is inferred from the key prefix. -
recipientrenamed toto; numbers reformatted to E.164. -
Idempotency-Keyheader generated per logical send and reused on retry. -
max_attemptsset per fax where the default of 3 attempts is not the right ceiling. - Receiver code verifies Standard Webhooks signatures via the reference library;
event_hashcheck removed. - Event handler routes on
event.type(valuesfax.queued,fax.sending,fax.delivered,fax.failed) and dedupes onevent.id. - 429 handler backs off and retries on
rate_limit_exceeded, reusing the sameIdempotency-Keyacross attempts. - Sandbox round-trip complete:
+15005550001returns afax_-prefixed ID, transitions throughqueuedandsubmitted, and ends indeliveredwith a valid webhook signature. -
+15005550004verifies the retry path;+15005550008verifies terminal short-circuit;+15005550099verifies validation rejection. - BAA (and DPA if applicable) accepted in the dashboard before the first live key.
- Feature flag in place at the receiver so a single deploy flips between the Dropbox Fax API and mintfax per request.
What to do next
- Verify webhook signatures - Standard Webhooks contract and reference-library snippets beyond Node.
- Idempotency keys - full 24-hour replay window and generation strategy.
- Errors - error-code catalog with
actionhints. - Event types - every event type, payload shape, and delivery guarantee.
- Sandbox testing - the nine magic numbers and their outcomes.
- Dropbox Fax API alternative - side-by-side comparison of the two products.