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.

You are adding fax to your product. Your customers will send faxes through your platform, and you need to decide how to structure the integration so that each customer’s traffic, billing, and compliance stay separate. mintfax’s environment model gives you two options: one environment per customer, or a shared environment where you handle tenant isolation yourself. This guide covers both patterns, the tradeoffs, and the operational details that matter when you go live.

Environment-per-customer

Create a separate mintfax environment for each of your customers. Every environment gets its own webhook configuration, retention settings, fax history, audit log, and (optionally) its own BAA. API keys are scoped per environment, so each customer’s traffic uses their own key. Credits live at the account, so all environments under one account share the typed credit pool. When to use this pattern:
  • Your customers have different compliance requirements. A healthcare customer needs a BAA and zero-footprint retention; a logistics customer does not.
  • You want operational isolation. Each environment has separate fax records, webhook endpoints, and audit logs - never shared across customers.
  • You need per-customer audit trails. Audit logs are scoped per environment, which simplifies compliance reporting.
  • You are building a platform where each customer might eventually want direct access to their own mintfax dashboard.
How it works in practice:
  1. When a customer signs up for fax on your platform, your backend creates a mintfax environment via the API.
  2. Your backend stores the environment’s API key in your secrets manager, mapped to the customer’s tenant ID.
  3. When that customer sends a fax through your product, your backend authenticates to mintfax using that customer’s environment key.
  4. Webhooks arrive at your endpoint with the environment context, so you know which customer the event belongs to.
Environments are typed at creation as sandbox or live. Most teams using this pattern keep a single shared sandbox environment for internal QA and create live environments per customer in production.

Shared environment

Use a single mintfax environment for all of your customers. You manage tenant isolation in your own application layer. When to use this pattern:
  • All customers share the same compliance posture and retention settings.
  • You have a small number of customers or are early-stage and want the simplest integration.
How it works in practice:
  1. Your backend holds one set of mintfax API keys (sandbox and live).
  2. When any customer sends a fax, your backend submits it using the shared key.
  3. You use the per-fax webhook_url parameter (covered below) to route delivery notifications to customer-specific handlers, or you fan out from a single webhook endpoint using fax metadata you store on your side.
  4. You track credit consumption per customer in your own database using fax records and webhook events.
The tradeoff is clear: simpler setup, but you own the isolation. If one customer needs a BAA or different retention rules, you need a separate environment for that customer.

Credential management

Regardless of which pattern you choose, one rule is absolute: your backend holds the API keys. Never expose mintfax credentials to your end users’ browsers, mobile apps, or client-side code. Your architecture should look like this:
End user -> Your frontend -> Your backend -> mintfax API
Your backend authenticates to mintfax, submits the fax, and returns the result to your frontend. The API key never leaves your server. Store keys in environment variables or a secrets manager. If you use the environment-per-customer pattern, your secrets store maps each tenant ID to its mintfax API key. Rotate keys through the dashboard - both the old and new keys work simultaneously during the transition, so you can update your secrets store without downtime.

Webhook routing

When a fax is delivered or fails, mintfax sends a webhook event. In a multi-tenant setup, you need each event to reach the right customer’s processing logic.

Option 1: Per-fax webhook URL

Pass webhook_url on each POST /v1/faxes request to override the environment-level webhook endpoint. This lets you route callbacks to a customer-specific URL or a URL that encodes the tenant context.
curl -X POST https://api.mintfax.com/v1/faxes \
  -H "Authorization: Bearer mfx_live_abc123..." \
  -H "Idempotency-Key: $(uuidgen)" \
  -F "to=+12125551234" \
  -F "file=@document.pdf" \
  -F "webhook_url=https://yourapp.com/webhooks/mintfax/tenant/cust_8xk2m"
Your webhook handler parses the tenant ID from the URL path and processes the event in that customer’s context. This approach works well with the shared environment pattern - you get per-customer routing without managing multiple environments.

Option 2: Fan-out from a single endpoint

Configure one webhook endpoint on the environment and fan out internally. When you submit a fax, store the fax ID alongside the customer’s tenant ID in your database. When the webhook arrives, look up the fax ID to determine which customer it belongs to, then route accordingly.
{
  "id": "evt_01J9XYZQ8KH7B3R0WXAZP8VW6H",
  "type": "fax.delivered",
  "created": 1730000008,
  "data": {
    "object": {
      "id": "fax_8aZqRm4yT3vK7pNxJ2bH9c",
      "status": "delivered"
    }
  }
}
Your handler receives this, looks up fax ID fax_8aZqRm4yT3vK7pNxJ2bH9c in your database, finds it belongs to cust_8xk2m, and processes accordingly.

Which to choose

Per-fax webhook URLs are simpler if you want stateless routing - the tenant context is in the URL itself. Fan-out is better if you want a single ingestion point with centralized signature verification and logging. Both approaches work with either environment pattern. Verify every webhook payload using the HMAC-SHA256 signature. See Webhook signing for verification recipes in multiple languages.

Billing pass-through

If you charge your customers for faxing, you need to track what each customer consumes. Environment-per-customer: Credits pool at the account, so all environments under one account share the typed credit balance. To meter customers individually for invoicing, track fax submissions in your own database keyed by tenant ID and bill from your record. Subscribe to balance.low webhook events to alert your system when the shared pool runs low. If you need true per-customer prepaid isolation (separate balance each), create a separate mintfax account per customer rather than a separate environment - the API supports programmatic account registration. Shared environment: You own the accounting. When you submit a fax, record the fax ID and customer in your database. When you receive a fax.delivered or fax.failed webhook, update the customer’s usage record. Delivered faxes consume credits (per page); failed faxes release the hold and cost nothing. The credit lifecycle is hold-capture-release:
  1. On submission, mintfax places a hold for the estimated cost.
  2. On delivery, the hold is captured as a permanent charge.
  3. On failure, the hold is released back to the available balance.
See Credits for the full lifecycle and balance queries.

Idempotency in multi-tenant systems

Idempotency keys are scoped per environment, not globally. If two customers in different environments happen to use the same idempotency key, there is no collision because each environment maintains its own keyspace. In a shared environment, all customers’ keys share one keyspace, so generate unique keys per fax submission regardless of which customer triggered it. Keys expire after 24 hours. See Idempotency for the full behavior.

Compliance considerations

If any of your customers handle protected health information, you need environment-level compliance controls. BAA: mintfax signs a BAA per environment at no extra cost. If you use the environment-per-customer pattern, you can sign a BAA for the environments that need it and skip it for those that do not. If you use a shared environment and any customer needs a BAA, you sign one for the shared environment. Retention: Each environment can be configured for standard retention (configurable window, default 90 days) or zero-footprint mode (data deleted after the fax reaches a terminal state). Healthcare customers typically want zero-footprint mode. In the environment-per-customer pattern, you set the retention mode per environment. In a shared environment, all customers share the same retention policy. The environment-per-customer pattern is strongly recommended for healthcare SaaS. It gives you per-customer BAAs, per-customer retention policies, and per-customer audit logs - exactly what you need for compliance reporting. See HIPAA compliance for the full compliance boundary and BAA signing process.

Testing multi-tenant flows

Use sandbox environments to test each tenant’s flow before going live.
  1. Use a sandbox environment for testing (the auto-provisioned one or a new one you create).
  2. Configure webhook endpoints and test with the sandbox magic numbers. +15005550001 simulates successful delivery; other magic numbers simulate failures.
  3. Verify that webhooks arrive at the correct per-tenant URL or that your fan-out logic routes to the right customer.
  4. Test the billing flow: submit faxes, confirm holds are placed, and verify that delivery events trigger the right credit accounting in your system.
  5. When everything works, switch to live keys. Sandbox and live are fully isolated - no data, settings, or history carries over.

What to do next

  • Authentication for API key types, rotation, and security practices.
  • Webhooks for event types, payload format, and delivery behavior.
  • Go live for the checklist to activate your live environment and start sending real faxes.
  • HIPAA compliance for BAA signing, retention controls, and the compliance boundary.
Last modified on May 14, 2026