Get started

Quickstart

Two flows cover almost every integration: send a fax and read the result, or receive a fax and pull the document. Each step below is a copy-paste curl call — expand a sample label to see the JSON that comes back. Replace placeholders after your account is approved — or log in to fill them automatically.

Outbound flow

  1. Fax_SendFax → you get a JobId
  2. WestFax calls your CallBackUrl when the job finishes
  3. Fax_GetFaxDescriptionsUsingIds → per-recipient result
Start sending

Inbound flow

  1. A fax lands → WestFax calls your inbound webhook
  2. Fax_GetFaxDescriptionsUsingIds → sender, pages, date
  3. Fax_GetFaxDocuments → the PDF
  4. Fax_ChangeFaxFilterValue → mark retrieved (optional)
Start receiving

Both flows need two values: your x-api-key (see Credentials) and a ProductId, which is the id of the fax line you are sending from or receiving on (see List fax lines). Every call accepts either the x-api-key header or Username/Password form fields.

Outbound fax flow — send, callback, status

1 Send the fax

Fax_SendFax — multipart with Files0. Returns the JobId in Result; hold on to it, it is the id every later call uses. Pass CallBackUrl so you do not have to poll. Destination last 4 digits pick the final Call Result, and the job stays Submitted for 2 minutes before it finalizes.

Numbers1=5552001111 → Call Result Sent after the 2-minute window.

curl -s -X POST "https://integrate.westfax.com/rest/Fax_SendFax/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -F "ProductId=YOUR_PRODUCT_ID" \
  -F "JobName=Sandbox Sent" \
  -F "Header=From sandbox" \
  -F "Numbers1=5552001111" \
  -F 'FaxQuality=Fine' \
  -F 'CSID=(970) 289-5979' \
  -F 'CallBackUrl=[GET]http://yourweburl.com/{@jobid}?prod={@prodid}&dir={@dir}' \
  -F "Files0=@./your-document.pdf;type=application/pdf"

Numbers1=5552002222 → Call Result Busy after the 2-minute window.

curl -s -X POST "https://integrate.westfax.com/rest/Fax_SendFax/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -F "ProductId=YOUR_PRODUCT_ID" \
  -F "JobName=Sandbox Busy" \
  -F "Header=From sandbox" \
  -F "Numbers1=5552002222" \
  -F 'FaxQuality=Fine' \
  -F 'CSID=(970) 289-5979' \
  -F 'CallBackUrl=[GET]http://yourweburl.com/{@jobid}?prod={@prodid}&dir={@dir}' \
  -F "Files0=@./your-document.pdf;type=application/pdf"

Numbers1=5552003333 → Call Result OperatorIntercept after the 2-minute window.

curl -s -X POST "https://integrate.westfax.com/rest/Fax_SendFax/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -F "ProductId=YOUR_PRODUCT_ID" \
  -F "JobName=Sandbox Disconnected" \
  -F "Header=From sandbox" \
  -F "Numbers1=5552003333" \
  -F 'FaxQuality=Fine' \
  -F 'CSID=(970) 289-5979' \
  -F 'CallBackUrl=[GET]http://yourweburl.com/{@jobid}?prod={@prodid}&dir={@dir}' \
  -F "Files0=@./your-document.pdf;type=application/pdf"

Numbers1=5552004444 → Call Result Failed after the 2-minute window.

curl -s -X POST "https://integrate.westfax.com/rest/Fax_SendFax/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -F "ProductId=YOUR_PRODUCT_ID" \
  -F "JobName=Sandbox Failed" \
  -F "Header=From sandbox" \
  -F "Numbers1=5552004444" \
  -F 'FaxQuality=Fine' \
  -F 'CSID=(970) 289-5979' \
  -F 'CallBackUrl=[GET]http://yourweburl.com/{@jobid}?prod={@prodid}&dir={@dir}' \
  -F "Files0=@./your-document.pdf;type=application/pdf"

Numbers1=5552005555 → Call Result NoAnswer after the 2-minute window.

curl -s -X POST "https://integrate.westfax.com/rest/Fax_SendFax/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -F "ProductId=YOUR_PRODUCT_ID" \
  -F "JobName=Sandbox NoAnswer" \
  -F "Header=From sandbox" \
  -F "Numbers1=5552005555" \
  -F 'FaxQuality=Fine' \
  -F 'CSID=(970) 289-5979' \
  -F 'CallBackUrl=[GET]http://yourweburl.com/{@jobid}?prod={@prodid}&dir={@dir}' \
  -F "Files0=@./your-document.pdf;type=application/pdf"

Self-send tip: set Numbers1 to your own fax line 555-200-0000 with a Success last-4 (1111 or any unlisted ending). That delivers an outbound job and drops an inbound fax on the line, which gives you something real to walk the inbound flow with.

Sample responses

{
    "Success": true,
    "Result": "f9e8d7c6-b5a4-3210-9876-543210fedcba"
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadUsernamePassword",
    "InfoString": "Authorization Failed (Bad Username or Password)"
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadProductId",
    "InfoString": "Authorization Failed (Bad Product Id)"
}
{
    "Success": false,
    "ErrorString": "Handler_Failed_",
    "InfoString": "Handler_Failed_MissingParameters: Numbers"
}
{
    "Success": false,
    "ErrorString": "Handler_Failed_",
    "InfoString": "Handler_Failed_MissingParameters: Files"
}

2 Receive the job callback

When the job finishes — sent, busy, failed, any outcome — WestFax calls the CallBackUrl you passed to Fax_SendFax. That is your signal to go read the status; you should not poll on a timer. The method prefix picks GET or POST, and the three variables are substituted for you:

[GET]https://example.com/webhooks/fax/out?prodid={@prodid}&jobId={@jobid}&dir={@dir}

{@prodid}  the fax line the job was sent from  -> ProductId
{@jobid}   the job id (same value Fax_SendFax returned) -> FaxIds1
{@dir}     outbound

So your endpoint sees a request like this:

POST /webhooks/fax/out HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded

jobId=f9e8d7c6-b5a4-3210-9876-543210fedcba&prodid=YOUR_PRODUCT_ID&dir=outbound
Return 200 immediately, then do your work asynchronously. If you call other APIs or run queries before responding, the callback can time out and be delivered again — so make your handler idempotent. Anything slower than 10 seconds is treated as slow.

The callback carries no result detail on purpose: one job can fax many recipients, and each one has its own outcome. It tells you the job is done — step 3 tells you what happened.

Your callback URL is public, so validate the jobId against jobs you actually submitted, use HTTPS, and allowlist our delivery IP 34.125.215.21. You can also append your own static params (e.g. &key=…) as a shared secret.

In the sandbox: nothing fires on its own. Save a template on Webhooks, then use Fire webhook on a row in Faxes to send yourself a real callback and watch it land in the inspector.

3 Read the result

Fax_GetFaxDescriptionsUsingIds — feed it the prodid and jobId from the callback. Check both levels of status: Status is the job (Complete means "done trying", not "delivered"), and each entry in FaxCallInfoList carries the real per-recipient Result — Sent, Busy, NoAnswer, Failed, and so on. A job with four recipients has four entries, so loop them all.

curl -s -X POST "https://integrate.westfax.com/rest/Fax_GetFaxDescriptionsUsingIds/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -d "ProductId=YOUR_PRODUCT_ID" \
  -d 'FaxIds1={"Id":"f9e8d7c6-b5a4-3210-9876-543210fedcba","Direction":"Outbound"}'

Sample responses

{
    "Success": true,
    "Result": [
        {
            "FaxCallInfoList": [
                {
                    "CallId": "11111111-2222-3333-4444-555555555555",
                    "CompletedUTC": "2026-06-15T18:02:00Z",
                    "TermNumber": "5552001111",
                    "OrigNumber": "5552000000",
                    "TermCSID": "(970) 289-5979",
                    "OrigCSID": "(970) 289-5979",
                    "Result": "Sent",
                    "CallPageCount": 1,
                    "FilterFlag": 0
                }
            ],
            "Id": "f9e8d7c6-b5a4-3210-9876-543210fedcba",
            "Date": "2026-06-15T18:00:00Z",
            "Direction": "Outbound",
            "Tag": "None",
            "PageCount": 1,
            "FaxQuality": "Fine",
            "Status": "Complete",
            "Reference": "f9e8d7c6-b5a4-3210-9876-543210fedcba",
            "JobName": "Sandbox Sent",
            "CreatedBy": "YOUR_EMAIL",
            "LoginId": "00000000-0000-0000-0000-000000000000",
            "CreatedVia": "ApiRest",
            "DocPageCount": 0,
            "FilterValue": "None",
            "FolderId": "00000000-0000-0000-0000-000000000000",
            "FilesAvailable": false,
            "ProcessingState": "Final"
        }
    ]
}
{
    "Success": true,
    "Result": [
        {
            "FaxCallInfoList": [
                {
                    "CallId": "11111111-2222-3333-4444-555555555555",
                    "CompletedUTC": null,
                    "TermNumber": "5552001111",
                    "OrigNumber": "5552000000",
                    "TermCSID": "(970) 289-5979",
                    "OrigCSID": "(970) 289-5979",
                    "Result": "Dialing",
                    "CallPageCount": 1,
                    "FilterFlag": 0
                }
            ],
            "Id": "f9e8d7c6-b5a4-3210-9876-543210fedcba",
            "Date": "2026-06-15T18:00:00Z",
            "Direction": "Outbound",
            "Tag": "None",
            "PageCount": 1,
            "FaxQuality": "Fine",
            "Status": "Submitted",
            "Reference": "f9e8d7c6-b5a4-3210-9876-543210fedcba",
            "JobName": "Sandbox Sent",
            "CreatedBy": "YOUR_EMAIL",
            "LoginId": "00000000-0000-0000-0000-000000000000",
            "CreatedVia": "ApiRest",
            "DocPageCount": 0,
            "FilterValue": "None",
            "FolderId": "00000000-0000-0000-0000-000000000000",
            "FilesAvailable": false,
            "ProcessingState": "Processing"
        }
    ]
}
{
    "Success": true,
    "Result": [
        {
            "FaxCallInfoList": [
                {
                    "CallId": "11111111-2222-3333-4444-555555555555",
                    "CompletedUTC": "2026-06-15T18:02:00Z",
                    "TermNumber": "5552002222",
                    "OrigNumber": "5552000000",
                    "TermCSID": "(970) 289-5979",
                    "OrigCSID": "(970) 289-5979",
                    "Result": "Busy",
                    "CallPageCount": 1,
                    "FilterFlag": 0
                }
            ],
            "Id": "f9e8d7c6-b5a4-3210-9876-543210fedcba",
            "Date": "2026-06-15T18:00:00Z",
            "Direction": "Outbound",
            "Tag": "None",
            "PageCount": 1,
            "FaxQuality": "Fine",
            "Status": "Complete",
            "Reference": "f9e8d7c6-b5a4-3210-9876-543210fedcba",
            "JobName": "Sandbox Sent",
            "CreatedBy": "YOUR_EMAIL",
            "LoginId": "00000000-0000-0000-0000-000000000000",
            "CreatedVia": "ApiRest",
            "DocPageCount": 0,
            "FilterValue": "None",
            "FolderId": "00000000-0000-0000-0000-000000000000",
            "FilesAvailable": false,
            "ProcessingState": "Final"
        }
    ]
}
{
    "Success": true,
    "Result": []
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadUsernamePassword",
    "InfoString": "Authorization Failed (Bad Username or Password)"
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadProductId",
    "InfoString": "Authorization Failed (Bad Product Id)"
}

Batch up to 10 ids per call (FaxIds1…FaxIds10). Unknown or foreign ids are silently dropped rather than erroring, so an empty Result means "no fax by that id on that line". On outbound jobs FilesAvailable always reports false — a real-API quirk kept here on purpose; the document is still fetchable with Fax_GetFaxDocuments.

Inbound fax flow — callback, metadata, document

1 Receive the inbound callback

When a fax arrives on one of your lines, WestFax calls the webhook registered for that line. Same shape as the outbound callback, with dir=inbound:

POST /webhooks/fax/inbound HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded

jobid=a1b2c3d4-e5f6-7890-abcd-ef1234567890&prodid=YOUR_PRODUCT_ID&dir=inbound

Reply 200 right away and queue the work — the fax and its pages are already stored on our side, so there is no rush to download inside the handler. Param names are configurable; prodid and jobid are just our defaults.

Register the URL per fax line on Webhooks (the bulk editor applies one URL to many lines at once). In the sandbox, create an inbound fax to play with by using Spawn inbound on Faxes, or by sending to your own fax line 555-200-0000 in step 1 of the outbound flow.

2 Get the fax metadata

Same call as the outbound status step, with Direction set to Inbound. This tells you who sent it (OrigNumber / OrigCSID), how many pages (PageCount), when it landed, and whether the document is ready (FilesAvailable). Inbound calls always report Result: Success — a fax that did not complete never becomes a fax.

curl -s -X POST "https://integrate.westfax.com/rest/Fax_GetFaxDescriptionsUsingIds/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -d "ProductId=YOUR_PRODUCT_ID" \
  -d 'FaxIds1={"Id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","Direction":"Inbound"}'

Sample responses

{
    "Success": true,
    "Result": [
        {
            "FaxCallInfoList": [
                {
                    "CallId": "11111111-2222-3333-4444-555555555555",
                    "CompletedUTC": "2026-06-15T18:02:00Z",
                    "TermNumber": "5552000000",
                    "OrigNumber": "5552001111",
                    "TermCSID": "(970) 289-5979",
                    "OrigCSID": "(970) 289-5979",
                    "Result": "Success",
                    "CallPageCount": 1,
                    "FilterFlag": 0
                }
            ],
            "Id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "Date": "2026-06-15T18:00:00Z",
            "Direction": "Inbound",
            "Tag": "None",
            "PageCount": 1,
            "FaxQuality": "Fine",
            "Status": "Complete",
            "Reference": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "JobName": "Fax from (970) 289-5979",
            "CreatedBy": "System",
            "LoginId": "00000000-0000-0000-0000-000000000000",
            "CreatedVia": "InboundCall",
            "DocPageCount": 0,
            "FilterValue": "None",
            "FolderId": "00000000-0000-0000-0000-000000000000",
            "FilesAvailable": true,
            "ProcessingState": "Final"
        }
    ]
}
{
    "Success": true,
    "Result": [
        {
            "FaxCallInfoList": [
                {
                    "CallId": "11111111-2222-3333-4444-555555555555",
                    "CompletedUTC": "2026-06-15T18:02:00Z",
                    "TermNumber": "5552000000",
                    "OrigNumber": "5552001111",
                    "TermCSID": "(970) 289-5979",
                    "OrigCSID": "(970) 289-5979",
                    "Result": "Success",
                    "CallPageCount": 1,
                    "FilterFlag": 0
                }
            ],
            "Id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "Date": "2026-06-15T18:00:00Z",
            "Direction": "Inbound",
            "Tag": "Retrieved",
            "PageCount": 1,
            "FaxQuality": "Fine",
            "Status": "Complete",
            "Reference": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "JobName": "Fax from (970) 289-5979",
            "CreatedBy": "System",
            "LoginId": "00000000-0000-0000-0000-000000000000",
            "CreatedVia": "InboundCall",
            "DocPageCount": 0,
            "FilterValue": "Retrieved",
            "FolderId": "00000000-0000-0000-0000-000000000000",
            "FilesAvailable": true,
            "ProcessingState": "Final"
        }
    ]
}
{
    "Success": true,
    "Result": []
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadUsernamePassword",
    "InfoString": "Authorization Failed (Bad Username or Password)"
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadProductId",
    "InfoString": "Authorization Failed (Bad Product Id)"
}

3 Download the document

Fax_GetFaxDocuments — one entry per requested id (up to 10), with the file base64-encoded in FaxFiles[].FileContents. Format accepts pdf or tiff; the sandbox always hands back the canonical one-page test PDF.

curl -s -X POST "https://integrate.westfax.com/rest/Fax_GetFaxDocuments/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -d "ProductId=YOUR_PRODUCT_ID" \
  -d "Format=pdf" \
  -d 'FaxIds1={"Id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","Direction":"Inbound"}'

Straight to a file on disk:

curl -s -X POST "https://integrate.westfax.com/rest/Fax_GetFaxDocuments/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -d "ProductId=YOUR_PRODUCT_ID" \
  -d "Format=pdf" \
  -d 'FaxIds1={"Id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","Direction":"Inbound"}' \
  | jq -r '.Result[0].FaxFiles[0].FileContents' | base64 -d > fax.pdf

Sample responses

{
    "Success": true,
    "Result": [
        {
            "FaxFiles": [
                {
                    "ContentType": "application/pdf",
                    "ContentLength": 12345,
                    "FileContents": "<base64 truncated\u2026>"
                }
            ],
            "Id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "Direction": "Inbound",
            "Date": "2026-06-15T18:00:00Z",
            "Status": "Ok",
            "Format": "pdf",
            "PageCount": 1
        }
    ]
}
{
    "Success": true,
    "Result": []
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadUsernamePassword",
    "InfoString": "Authorization Failed (Bad Username or Password)"
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadProductId",
    "InfoString": "Authorization Failed (Bad Product Id)"
}
{
    "Success": false,
    "ErrorString": "Handler_Failed_",
    "InfoString": "Handler_Failed_MissingParameters: FaxIds"
}

4 Mark it retrieved (optional)

Fax_ChangeFaxFilterValue closes the loop: once you have stored the document, tag the fax Retrieved (read) so you can tell processed faxes from new ones, or Removed (deleted) to take it out of your working set. None puts it back to unread. The value comes back as Tag / FilterValue on the description calls, so it doubles as your own "already handled" flag. Up to 10 ids per call.

Nothing is destroyed: Removed faxes stay listed with Tag: Removed, and any valid value on a valid fax succeeds — re-marking a read fax, or undeleting one, is fine. A bad fax id is the one failure case here, which is the opposite of the description calls above (they just omit it).

curl -s -X POST "https://integrate.westfax.com/rest/Fax_ChangeFaxFilterValue/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -d "ProductId=YOUR_PRODUCT_ID" \
  -d "Filter=Retrieved" \
  -d 'FaxIds1={"Id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","Direction":"Inbound"}'

Sample responses

{
    "Success": true,
    "Result": true
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadUsernamePassword",
    "InfoString": "Authorization Failed (Bad Username or Password)"
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadProductId",
    "InfoString": "Authorization Failed (Bad Product Id)"
}
{
    "Success": false,
    "ErrorString": "Handler_Failed_",
    "InfoString": "Handler_Failed_MissingParameters: FaxIds"
}
{
    "Success": false,
    "ErrorString": "Api_Failed_",
    "InfoString": "Api_Failed_"
}

Full narrative version of both flows, including retry and security guidance: Fax API integration guide.

Setup & reference

Authenticate

Security_Authenticate — Username (your email) + Password only (no api-key). Session id is throwaway; later calls re-auth each time.

curl -s -X POST "https://integrate.westfax.com/rest/Security_Authenticate/json" \
  -d "Username=YOUR_EMAIL" \
  -d "Password=YOUR_SIM_PASSWORD"

Sample responses

{
    "Success": true,
    "Result": "A1B2C3D4E5F6789012345678ABCDEF01"
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadUsernamePassword",
    "InfoString": "Login Failed."
}

List fax lines

Profile_GetF2EProductList — returns your fax lines. Use a returned Id as ProductId on later calls (that field name is the fax line id). Example uses x-api-key header.

curl -s -X POST "https://integrate.westfax.com/rest/Profile_GetF2EProductList/json" \
  -H "x-api-key: YOUR_X_API_KEY"

Sample responses

{
    "Success": true,
    "Result": [
        {
            "Id": "YOUR_PRODUCT_ID",
            "Name": "555-200-0000",
            "ProductType": "FaxForward",
            "PlanId": "1fedf262-5042-4f3a-b368-8d975e60d6f7",
            "InboundNumber": "5552000000",
            "TimeZone": "Pacific",
            "ProductState": "OK",
            "CurrentBillingPeriodStart": "2026-10-01T00:00:00Z",
            "CurrentBillingPeriodEnd": "2026-11-01T00:00:00Z",
            "FreeTrialEnd": "2027-01-15T23:59:59Z",
            "PeriodicQuantity": 0,
            "QuantityInbound": 0,
            "QuantityOutbound": 0,
            "ShowDeletedItemsFolder": true,
            "DefaultCoverPageId": "00000000-0000-0000-0000-000000000000"
        },
        {
            "Id": "YOUR_PRODUCT_ID_2",
            "Name": "555-200-0001",
            "ProductType": "FaxForward",
            "PlanId": "1fedf262-5042-4f3a-b368-8d975e60d6f7",
            "InboundNumber": "5552000001",
            "TimeZone": "Pacific",
            "ProductState": "OK",
            "CurrentBillingPeriodStart": "2026-10-01T00:00:00Z",
            "CurrentBillingPeriodEnd": "2026-11-01T00:00:00Z",
            "FreeTrialEnd": "2027-01-15T23:59:59Z",
            "PeriodicQuantity": 0,
            "QuantityInbound": 0,
            "QuantityOutbound": 0,
            "ShowDeletedItemsFolder": true,
            "DefaultCoverPageId": "00000000-0000-0000-0000-000000000000"
        }
    ]
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadUsernamePassword",
    "InfoString": "Authorization Failed (Bad Username or Password)"
}

List fax identifiers

Fax_GetFaxIdentifiers — ids only, filtered by direction + StartDate. Useful for backfilling or reconciling if you ever miss a callback.

curl -s -X POST "https://integrate.westfax.com/rest/Fax_GetFaxIdentifiers/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -d "ProductId=YOUR_PRODUCT_ID" \
  -d "FaxDirection=Outbound" \
  -d "StartDate=1/1/2020"

Sample responses

{
    "Success": true,
    "Result": [
        {
            "Id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "Direction": "Outbound",
            "Date": "2026-06-15T18:00:00Z",
            "Tag": "None"
        },
        {
            "Id": "f9e8d7c6-b5a4-3210-9876-543210fedcba",
            "Direction": "Outbound",
            "Date": "2026-06-14T12:00:00Z",
            "Tag": "Retrieved"
        }
    ]
}
{
    "Success": true,
    "Result": []
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadUsernamePassword",
    "InfoString": "Authorization Failed (Bad Username or Password)"
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadProductId",
    "InfoString": "Authorization Failed (Bad Product Id)"
}

Descriptions by date range

Fax_GetFaxDescriptions — the same objects as the flow steps above, but for a whole direction and date range instead of specific ids (2-minute rule applied at read time).

curl -s -X POST "https://integrate.westfax.com/rest/Fax_GetFaxDescriptions/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -d "ProductId=YOUR_PRODUCT_ID" \
  -d "FaxDirection=Outbound" \
  -d "StartDate=1/1/2020"

Sample responses

{
    "Success": true,
    "Result": [
        {
            "FaxCallInfoList": [
                {
                    "CallId": "11111111-2222-3333-4444-555555555555",
                    "CompletedUTC": "2026-06-15T18:02:00Z",
                    "TermNumber": "5552001111",
                    "OrigNumber": "5552000000",
                    "TermCSID": "(970) 289-5979",
                    "OrigCSID": "(970) 289-5979",
                    "Result": "Sent",
                    "CallPageCount": 1,
                    "FilterFlag": 0
                }
            ],
            "Id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "Date": "2026-06-15T18:00:00Z",
            "Direction": "Outbound",
            "Tag": "None",
            "PageCount": 1,
            "FaxQuality": "Fine",
            "Status": "Complete",
            "Reference": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "JobName": "Sandbox Sent",
            "CreatedBy": "YOUR_EMAIL",
            "LoginId": "00000000-0000-0000-0000-000000000000",
            "CreatedVia": "ApiRest",
            "DocPageCount": 0,
            "FilterValue": "None",
            "FolderId": "00000000-0000-0000-0000-000000000000",
            "FilesAvailable": false,
            "ProcessingState": "Final"
        }
    ]
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadUsernamePassword",
    "InfoString": "Authorization Failed (Bad Username or Password)"
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadProductId",
    "InfoString": "Authorization Failed (Bad Product Id)"
}

Paged search

Fax_GetF2EFaxDescriptions_PagedSearch — page/count via MethodParams; optional dates and filters.

curl -s -X POST "https://integrate.westfax.com/rest/Fax_GetF2EFaxDescriptions_PagedSearch/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -d "ProductId=YOUR_PRODUCT_ID" \
  -d "FaxDirection=Inbound" \
  --data-urlencode 'MethodParams1={"Name":"page","Value":"1"}' \
  --data-urlencode 'MethodParams2={"Name":"count","Value":"25"}'

Sample responses

{
    "Success": true,
    "Result": {
        "TotalItems": 1,
        "PageNumber": 1,
        "ItemsPerPage": 25,
        "Items": [
            {
                "FaxCallInfoList": [
                    {
                        "CallId": "11111111-2222-3333-4444-555555555555",
                        "CompletedUTC": "2026-06-15T18:02:00Z",
                        "TermNumber": "5552001111",
                        "OrigNumber": "5552000000",
                        "TermCSID": "(970) 289-5979",
                        "OrigCSID": "(970) 289-5979",
                        "Result": "Success",
                        "CallPageCount": 1,
                        "FilterFlag": 0
                    }
                ],
                "Id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                "Date": "2026-06-15T18:00:00Z",
                "Direction": "Inbound",
                "Tag": "None",
                "PageCount": 1,
                "FaxQuality": "Fine",
                "Status": "Complete",
                "Reference": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                "JobName": "Sandbox Sent",
                "CreatedBy": "System",
                "LoginId": "00000000-0000-0000-0000-000000000000",
                "CreatedVia": "InboundCall",
                "DocPageCount": 0,
                "FilterValue": "None",
                "FolderId": "00000000-0000-0000-0000-000000000000",
                "FilesAvailable": true,
                "ProcessingState": "Final",
                "FaxId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
            }
        ]
    }
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadUsernamePassword",
    "InfoString": "Authorization Failed (Bad Username or Password)"
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadProductId",
    "InfoString": "Authorization Failed (Bad Product Id)"
}
{
    "Success": false,
    "ErrorString": "Handler_Failed_",
    "InfoString": "Handler_Failed_MissingParameters: page,count"
}

Fax usage

Profile_GetFaxUsageByProductId — inbound/outbound counts for a date span (max 32 days) on one fax line. CurrentBillingPeriodStart/End echo the requested range; quantities count sandbox faxes in that window.

curl -s -X POST "https://integrate.westfax.com/rest/Profile_GetFaxUsageByProductId/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -d "ProductId=YOUR_PRODUCT_ID" \
  -d "StartDate=6/1/2026 12:00:00AM" \
  -d "EndDate=7/1/2026 12:00:00AM"

Sample responses

{
    "Success": true,
    "Result": {
        "Id": "YOUR_PRODUCT_ID",
        "Name": "555-200-0000",
        "ProductType": "FaxForward",
        "PlanId": "1fedf262-5042-4f3a-b368-8d975e60d6f7",
        "InboundNumber": "5552000000",
        "TimeZone": "Pacific",
        "ProductState": "OK",
        "CurrentBillingPeriodStart": "2026-06-01T00:00:00Z",
        "CurrentBillingPeriodEnd": "2026-07-01T00:00:00Z",
        "FreeTrialEnd": "2027-01-15T23:59:59Z",
        "PeriodicQuantity": 0,
        "QuantityInbound": 51,
        "QuantityOutbound": 79,
        "ShowDeletedItemsFolder": true,
        "DefaultCoverPageId": "00000000-0000-0000-0000-000000000000"
    }
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadUsernamePassword",
    "InfoString": "Authorization Failed (Bad Username or Password)"
}
{
    "Success": false,
    "ErrorString": "Handler_Failed_",
    "InfoString": "Handler_Failed_MissingParameters: ProductId"
}
{
    "Success": false,
    "ErrorString": "Api_Failed_",
    "InfoString": "Api_Failed_"
}
{
    "Success": false,
    "ErrorString": "Api_Failed_Action_Not_Allowed",
    "InfoString": "Timespan is more than 32 days"
}

Contacts

List contacts

Contact_GetContactList — what the key can see. Optional ProductId narrows to that fax line (Global + line Public + Private). No update endpoint — edit is save-then-delete. See the Contacts article.

curl -s -X POST "https://integrate.westfax.com/rest/Contact_GetContactList/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -d "Cookies=false"

Sample responses

{
    "Success": true,
    "Result": [
        {
            "Id": "11111111-1111-1111-1111-111111111111",
            "Title": "",
            "FirstName": "Jane",
            "LastName": "Doe",
            "CompanyName": "Acme Health",
            "Email": "",
            "EmailValidated": false,
            "Fax": "(555) 100-0001",
            "MobilePhone": "",
            "Phone": "",
            "Type": "Global",
            "OwnerId": "00000000-0000-0000-0000-000000000001",
            "OwnerDisplayName": "ACCT-00000001"
        },
        {
            "Id": "22222222-2222-2222-2222-222222222222",
            "Title": "",
            "FirstName": "John",
            "LastName": "Smith",
            "CompanyName": "Example Clinic",
            "Email": "john@example.org",
            "EmailValidated": false,
            "Fax": "5551000002",
            "MobilePhone": "",
            "Phone": "5551000099",
            "Type": "Public",
            "OwnerId": "00000000-0000-0000-0000-000000000002",
            "OwnerDisplayName": "Shared Line"
        },
        {
            "Id": "33333333-3333-3333-3333-333333333333",
            "Title": "",
            "FirstName": "Sandra",
            "LastName": "Lopez",
            "CompanyName": "",
            "Email": "",
            "EmailValidated": false,
            "Fax": "(555) 100-0003",
            "MobilePhone": "",
            "Phone": "",
            "Type": "Private",
            "OwnerId": "00000000-0000-0000-0000-000000000003",
            "OwnerDisplayName": "YOUR_EMAIL"
        }
    ]
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadUsernamePassword",
    "InfoString": "Authorization Failed (Bad Username or Password)"
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadProductId",
    "InfoString": "Authorization Failed (Bad Product Id)"
}

All contacts

Contact_GetAllContactList — full dump for the account. In this sandbox it matches the unfiltered list (one user per account).

curl -s -X POST "https://integrate.westfax.com/rest/Contact_GetAllContactList/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -d "Cookies=false"

Sample responses

{
    "Success": true,
    "Result": [
        {
            "Id": "11111111-1111-1111-1111-111111111111",
            "Title": "",
            "FirstName": "Jane",
            "LastName": "Doe",
            "CompanyName": "Acme Health",
            "Email": "",
            "EmailValidated": false,
            "Fax": "(555) 100-0001",
            "MobilePhone": "",
            "Phone": "",
            "Type": "Global",
            "OwnerId": "00000000-0000-0000-0000-000000000001",
            "OwnerDisplayName": "ACCT-00000001"
        },
        {
            "Id": "22222222-2222-2222-2222-222222222222",
            "Title": "",
            "FirstName": "John",
            "LastName": "Smith",
            "CompanyName": "Example Clinic",
            "Email": "john@example.org",
            "EmailValidated": false,
            "Fax": "5551000002",
            "MobilePhone": "",
            "Phone": "5551000099",
            "Type": "Public",
            "OwnerId": "00000000-0000-0000-0000-000000000002",
            "OwnerDisplayName": "Shared Line"
        },
        {
            "Id": "33333333-3333-3333-3333-333333333333",
            "Title": "",
            "FirstName": "Sandra",
            "LastName": "Lopez",
            "CompanyName": "",
            "Email": "",
            "EmailValidated": false,
            "Fax": "(555) 100-0003",
            "MobilePhone": "",
            "Phone": "",
            "Type": "Private",
            "OwnerId": "00000000-0000-0000-0000-000000000003",
            "OwnerDisplayName": "YOUR_EMAIL"
        }
    ]
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadUsernamePassword",
    "InfoString": "Authorization Failed (Bad Username or Password)"
}

Send-fax picker (paged)

Contact_GetContactList_ForSend_PagedSearch — requires a fax line ProductId. MethodParams: page, count, optional searchString, filters, includeOnlyContactsWithEmail.

curl -s -X POST "https://integrate.westfax.com/rest/Contact_GetContactList_ForSend_PagedSearch/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -d "ProductId=YOUR_PRODUCT_ID" \
  -d "Cookies=false" \
  --data-urlencode 'MethodParams1={"Name":"page","Value":"1"}' \
  --data-urlencode 'MethodParams2={"Name":"count","Value":"25"}'

Sample responses

{
    "Success": true,
    "Result": {
        "TotalItems": 3,
        "PageNumber": 1,
        "ItemsPerPage": 25,
        "Items": [
            {
                "Id": "11111111-1111-1111-1111-111111111111",
                "Title": "",
                "FirstName": "Jane",
                "LastName": "Doe",
                "CompanyName": "Acme Health",
                "Email": "",
                "EmailValidated": false,
                "Fax": "(555) 100-0001",
                "MobilePhone": "",
                "Phone": "",
                "Type": "Global",
                "OwnerId": "00000000-0000-0000-0000-000000000001",
                "OwnerDisplayName": "ACCT-00000001"
            },
            {
                "Id": "22222222-2222-2222-2222-222222222222",
                "Title": "",
                "FirstName": "John",
                "LastName": "Smith",
                "CompanyName": "Example Clinic",
                "Email": "john@example.org",
                "EmailValidated": false,
                "Fax": "5551000002",
                "MobilePhone": "",
                "Phone": "5551000099",
                "Type": "Public",
                "OwnerId": "00000000-0000-0000-0000-000000000002",
                "OwnerDisplayName": "Shared Line"
            },
            {
                "Id": "33333333-3333-3333-3333-333333333333",
                "Title": "",
                "FirstName": "Sandra",
                "LastName": "Lopez",
                "CompanyName": "",
                "Email": "",
                "EmailValidated": false,
                "Fax": "(555) 100-0003",
                "MobilePhone": "",
                "Phone": "",
                "Type": "Private",
                "OwnerId": "00000000-0000-0000-0000-000000000003",
                "OwnerDisplayName": "YOUR_EMAIL"
            }
        ]
    }
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadUsernamePassword",
    "InfoString": "Authorization Failed (Bad Username or Password)"
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadProductId",
    "InfoString": "Authorization Failed (Bad Product Id)"
}
{
    "Success": false,
    "ErrorString": "Handler_Failed_",
    "InfoString": "Handler_Failed_MissingParameters: page,count"
}

Admin paged search

Contact_GetContactList_ForAdmin_PagedSearch — filters is a comma list: Global,Public,Private.

curl -s -X POST "https://integrate.westfax.com/rest/Contact_GetContactList_ForAdmin_PagedSearch/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -d "Cookies=false" \
  --data-urlencode 'MethodParams1={"Name":"page","Value":"1"}' \
  --data-urlencode 'MethodParams2={"Name":"count","Value":"50"}' \
  --data-urlencode 'MethodParams3={"Name":"filters","Value":"Global,Public"}' \
  --data-urlencode 'MethodParams4={"Name":"searchString","Value":"acme"}'

Sample responses

{
    "Success": true,
    "Result": {
        "TotalItems": 1,
        "PageNumber": 1,
        "ItemsPerPage": 50,
        "Items": [
            {
                "Id": "11111111-1111-1111-1111-111111111111",
                "Title": "",
                "FirstName": "Jane",
                "LastName": "Doe",
                "CompanyName": "Acme Health",
                "Email": "",
                "EmailValidated": false,
                "Fax": "(555) 100-0001",
                "MobilePhone": "",
                "Phone": "",
                "Type": "Global",
                "OwnerId": "00000000-0000-0000-0000-000000000001",
                "OwnerDisplayName": "ACCT-00000001"
            }
        ]
    }
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadUsernamePassword",
    "InfoString": "Authorization Failed (Bad Username or Password)"
}
{
    "Success": false,
    "ErrorString": "Handler_Failed_",
    "InfoString": "Handler_Failed_MissingParameters: page,count"
}

Save a contact

Contact_SaveContact — always creates (leave Id empty). Only Fax is required inside CrmContact. Type: Global (account), Public (this fax line), Private (one user — set OwnerId if creating for someone else).

curl -s -X POST "https://integrate.westfax.com/rest/Contact_SaveContact/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -d "ProductId=YOUR_PRODUCT_ID" \
  -d "Cookies=false" \
  --data-urlencode 'CrmContact={"FirstName":"John","LastName":"Test32","Fax":"3032993339","CompanyName":"Acme, LLC","Email":"JTest@acme.org","Phone":"3332223333","Type":"Public"}'

Sample responses

{
    "Success": true,
    "Result": true
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadUsernamePassword",
    "InfoString": "Authorization Failed (Bad Username or Password)"
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadProductId",
    "InfoString": "Authorization Failed (Bad Product Id)"
}
{
    "Success": false,
    "ErrorString": "Handler_Failed_",
    "InfoString": "Handler_Failed_MissingParameters: CrmContact"
}
{
    "Success": false,
    "ErrorString": "Handler_Failed_",
    "InfoString": "Handler_Failed_MissingParameters: Fax"
}
{
    "Success": false,
    "ErrorString": "Handler_Failed_",
    "InfoString": "Invalid Contact Type"
}

Delete a contact

Contact_DeleteContact — CrmContact needs Id (from a list call) and Type. No email is sent. To “edit”: save the replacement first, then delete the old Id.

curl -s -X POST "https://integrate.westfax.com/rest/Contact_DeleteContact/json" \
  -H "x-api-key: YOUR_X_API_KEY" \
  -d "Cookies=false" \
  --data-urlencode 'CrmContact={"Id":"11111111-1111-1111-1111-111111111111","Type":"Global"}'

Sample responses

{
    "Success": true,
    "Result": true
}
{
    "Success": false,
    "ErrorString": "Authorization_Failed_BadUsernamePassword",
    "InfoString": "Authorization Failed (Bad Username or Password)"
}
{
    "Success": false,
    "ErrorString": "Handler_Failed_",
    "InfoString": "Handler_Failed_MissingParameters: CrmContact"
}
{
    "Success": false,
    "ErrorString": "Handler_Failed_",
    "InfoString": "Handler_Failed_MissingParameters: Id"
}
{
    "Success": false,
    "ErrorString": "Handler_Failed_",
    "InfoString": "Contact not found"
}