> ## Documentation Index
> Fetch the complete documentation index at: https://developers.telnyx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Fax llms-full.txt

> Complete machine-readable documentation content for Fax (Other APIs) for AI agents and LLMs

# Telnyx Other APIs: Fax — Full Documentation

> Complete page content for Fax (Other APIs section) of the Telnyx developer docs ([https://developers.telnyx.com](https://developers.telnyx.com)).
> Root index: [https://developers.telnyx.com/llms.txt](https://developers.telnyx.com/llms.txt) · Lightweight index for this subsection: [https://developers.telnyx.com/development/llms/other-apis-fax-llms-txt.md](https://developers.telnyx.com/development/llms/other-apis-fax-llms-txt.md)

### Getting Started

> Source: [https://developers.telnyx.com/docs/programmable-fax/get-started.md](https://developers.telnyx.com/docs/programmable-fax/get-started.md)

## Introduction

Welcome to Telnyx Programmable Fax, a powerful tool that allows you to send and receive faxes seamlessly through HTTP endpoints. This guide will introduce you to the basics of setting up and using the Programmable Fax API.

## Prerequisites

Before you begin, you'll need to:

* Set up a Telnyx account. [Sign up](https://telnyx.com/sign-up) here if you haven't already.
* Obtain a phone number and create a Programmable Fax Application following our [Quickstart guide](/docs/programmable-fax/quickstart).
* Generate a Telnyx V2 API Authentication key via the [Telnyx Mission Control Portal](https://portal.telnyx.com/#/app/api-keys).

## Core Concepts

* Programmable Fax Application: Configure inbound traffic and authentication for your phone numbers.
* Outbound Voice Profile: Manage outbound traffic, billing, and allowed destinations.
* Webhooks: HTTP callbacks that notify your server about fax events.

## Hello World Example

Send Your First Fax Using cURL:

1. Authenticate Your Request: Include your API key in the header for authentication.
2. Specify Fax Details: Provide the media URL, connection ID (use your application id), and the 'to' and 'from' fax numbers in E.164 format.
3. Send the Fax:

```bash theme={null}
curl -X POST https://api.telnyx.com/v2/faxes \
--data-raw '{
  "connection_id": "234423",
  "media_url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
  "to": "+13127367276",
  "from": "+13125790015"
}' \
--header 'Authorization: Bearer YourAPIKey'
```

Replace placeholders with your actual data.

1. Verify the Response: Check for an HTTP 202 response indicating successful fax initiation

## Next Steps

* Explore advanced features like receiving faxes and detailed webhook management.
* Check out our detailed tutorials for comprehensive guidance.

## Additional Resources

* Visit our API documentation for in-depth understanding.
* Join our community forums for support and discussion

## Feedback

We value your feedback. If you have questions or need help troubleshooting, our support team is ready to assist. Contact us [here](https://support.telnyx.com/).

## Glossary

1. Programmable Fax Application: A configuration within the Telnyx platform used to manage inbound and outbound fax traffic. It includes settings for authentication and handling of fax transmissions.
2. Outbound Voice Profile: A setting in Telnyx that allows users to initiate outbound traffic, including faxes. It includes configurations for billing, traffic management, and permitted destinations.
3. Fax\_id: A unique identifier assigned to each fax transmission. It is used to track and manage specific fax communications within the Telnyx system.
4. Media\_url: The URL pointing to the document you wish to fax, typically in PDF format. This URL is included in the fax command to specify the fax content.
5. Connection\_id: An identifier for your specific application or connection within Telnyx, used to route the fax correctly and associate it with your account.
6. E.164 Format: An internationally-recognized format for phone numbers, used in specifying the 'to' and 'from' fields in fax commands.
7. Failure\_reason: A field in the webhook payload that provides the reason for a fax's failure, helping in troubleshooting and understanding delivery issues.
8. Ngrok: A tunneling tool used to expose a local server to the internet, often used for testing webhook endpoints in development environments.
9. cURL: A command-line tool used for sending requests to URLs, commonly used for interacting with APIs like Telnyx's Programmable Fax API.

***

### Quickstart

> Source: [https://developers.telnyx.com/docs/programmable-fax/quickstart.md](https://developers.telnyx.com/docs/programmable-fax/quickstart.md)

In this guide, you'll learn how to get started with Telnyx Programmable Fax within the Telnyx Portal. Just follow these simple steps:

1. Sign up for a Telnyx Account.
2. Create a Programmable Fax Application to configure how you connect your calls.
3. Buy or port a Phone Number.
4. Assign your number to the Programmable Fax Application.
5. Create an Outbound Voice Profile to configure your outbound call settings and assign it to your Programmable Fax Application.

***

## Step 1: Sign Up for a Telnyx Mission Control Portal account

Head to
telnyx.com/sign-up
to sign up for your free Telnyx account. It’ll give you access to our Mission Control Portal where you can buy phone numbers, set up and manage Programmable Fax Applications, and more.

## Step 2: Create a programmable fax application in the Telnyx portal

* Select
  "Programmable Fax"
  in the left-hand navigation menu.
* Click "Add New App".
* For testing purposes, you can set the webhook URL using an endpoint you create at
  [https://hookbin.com](https://hookbin.com)
  .

## Step 3: Buy a phone number

You can search for, buy, and provision new numbers, or port existing numbers - all within the Numbers section of the
Telnyx Portal
.

Simply click on "Numbers", then either "Search & Buy Numbers" or "Port Numbers" and follow the prompts.

> You can also do this programmatically via our **RESTful API**. Check out our documentation for number [searching](/api-reference/phone-number-search/list-available-phone-numbers) and [ordering](/api-reference/phone-number-orders/create-a-number-order).

## Step 4: Assign your phone number to the programmable fax application

Once your number has been purchased or ported, assign it to the Programmable Fax Application that you created in step 2. You can do this via the
My Numbers
section of the Portal.

![Docs Images (1)](https://images.ctfassets.net/4b49ta6b3nwj/2BJYzATnJpHLpozAjst37j/208a1637c3b0cefb7a5e40d4ede66226/Docs_Images__1_.png)

## Step 5: Create an outbound voice profile (not required for Inbound)

To initiate an outbound fax, you must create an Outbound Voice Profile and assign your Programmable Fax Application to it.

Select
"Outbound Voice Profiles"
on the left-hand navigation menu, click "+Add New Profile" and set up your profile name. Add the Programmable Fax Application you just created above, the traffic type, the service plan, and your desired billing method.

> You can also do this programmatically via our **RESTful API**. Check out our documentation for [Outbound Voice Profiles](/docs/voice/outbound-voice-profiles).

That’s it. You're all set to start integrating Telnyx with your applications.

## Where to next?

Head over to our tutorials to learn how to [send a fax](/docs/programmable-fax/send-a-fax-api) and [receive a fax](/docs/programmable-fax/receive-a-fax-api) via API.

After you [setup your development environment](/development) you can also dive deeper into [sending commands](/docs/programmable-fax/sending-commands) and [receiving webhooks](/docs/programmable-fax/receiving-webhooks).

***

### Receiving Webhooks

> Source: [https://developers.telnyx.com/docs/programmable-fax/receiving-webhooks.md](https://developers.telnyx.com/docs/programmable-fax/receiving-webhooks.md)

When you send a Programmable Fax command and receive a successful response (i.e. 200 OK), you can expect to receive a webhook. The webhook will be delivered to the primary URL specified on the Application associated with the call. If that URL does not resolve, or your application returns a non 200 OK response, the webhook will be delivered to the failover URL, if one has been specified.

In order to minimize webhook delivery time, Telnyx:

* does not enforce the order in which webhooks are delivered
* retries webhook delivery if your application does not respond within a certain time threshold.

As a result, you may encounter:

* out-of-order webhooks
* simultaneous (or near simultaneous) webhooks
* duplicate webhooks

Duplicate webhooks may cause your application to issue duplicate commands. You can instruct Telnyx to ignore duplicate commands by sending a command\_id parameter as part of your commands. Commands with duplicate `command_ids` within 60 seconds will be ignored.

## Example: Receiving a webhook from an outbound fax

When you place an outbound fax, you will receive a number of webhooks indicating the current status of the fax. The first webhook you will receive will have A queued status indicating that Telnyx successfully received the request to send the fax.

```json theme={null}
{
  "data": {
    "event_type": "fax.queued",
    "id": "3691d047-d22a-424d-80ed-fe871981aa6d",
    "occurred_at": "2020-04-22T19:32:12.538002Z",
    "record_type": "event",
    "payload": {
      "call_duration_secs": 50,
      "connection_id": "7267xxxxxxxxxxxxxx",
      "direction": "outbound",
      "fax_id": "b679398e-8b4c-46bd-8630-6797f1ab5228",
      "from": "+35319605860",
      "original_media_url": "https://www.telnyx.com/telnyx-fax/1.pdf",
      "partial_content": true,
      "status": "queued",
      "to": "+13129457420",
      "user_id": "a5b1dfa3-fd2e-4e02-8ea4-xxxxxxxxxxxx"
    }
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "http://example.com/webhooks"
  }
}
```

FIELD
VALUE
record\_type
Description of the record.
id
unique id for the webhook
event\_type
The type of event
occurred\_at
ISO-8601 datetime of when event occured
to
Destination number or SIP URI of the call
from
Number or SIP URI placing the call
fax\_id
Unique ID for the Programmable Fax
client\_state
Configurable state to track commands
status
Can be one of queued, media.processed, sending.started, delivered, failed

## Example: Receiving a webhook on successful fax delivery

```bash theme={null}
{
  "event_type": "fax.delivered",
  "id": "3320554f-6b74-4138-a74b-a1e2ec7eaf8b",
  "occurred_at": "2022-01-07T10:01:43.677850Z",
  "payload": {
    "call_duration_secs": 79,
    "connection_id": "1232154810234",
    "direction": "outbound",
    "fax_id": "c62be5bc-9b13-4b6c-abda-34dd8b541287",
    "from": "+19459457421",
    "original_media_url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
    "page_count": 1,
    "status": "delivered",
    "to": "+13129457420",
    "user_id": "bdaa1f9f-1018-4156-867d-6c4ac9f556eb"
  }
}
```

## Example: Receiving a webhook on failed fax delivery

```bash theme={null}
{
  "event_type": "fax.failed",
  "id": "d906ecda-db21-428e-9ca0-74dae7e7c144",
  "occurred_at": "2022-01-05T22:23:46.888808Z",
  "payload": {
    "connection_id": "1232154810234",
    "direction": "outbound",
    "failure_reason": "user_busy",
    "fax_id": "f7b303ed-674c-4962-951b-848380510893",
    "from": "+19459457421",
    "original_media_url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
    "status": "failed",
    "to": "+13129457420",
    "user_id": "417b0cc2-39e0-4ab9-b116-e56543649aa9"
  }
}
```

## Possible failure reasons

Inspect the `failure_reason` field in webhook's payload to debug failed deliveries of your faxes. The possible failure reasons are:

* `account_disabled`
* `connection_channel_limit_exceeded`
* `destination_invalid`
* `destination_not_in_countries_whitelist`
* `destination_not_in_service_plan`
* `destination_unreachable`
* `fax_initial_communication_timeout`
* `fax_signaling_error`
* `invalid_ecm_response_from_receiver`
* `no_outbound_profile`
* `outbound_profile_channel_limit_exceeded`
* `outbound_profile_daily_spend_limit_exceeded`
* `receiver_call_dropped`
* `receiver_communication_error`
* `receiver_decline`
* `receiver_incompatible_destination`
* `receiver_invalid_number_format`
* `receiver_no_answer`
* `receiver_no_response`
* `receiver_recovery_on_timer_expire`
* `receiver_unallocated_number`
* `service_unavailable`
* `unverified_destination_not_allowed`
* `unverified_origination_number`
* `user_busy`
* `user_channel_limit_exceeded`

***

### Sending Commands

> Source: [https://developers.telnyx.com/docs/programmable-fax/sending-commands.md](https://developers.telnyx.com/docs/programmable-fax/sending-commands.md)

A Programmable Fax API command is sent with a fax\_id. The fax\_id allows a user to communicate to Telnyx the fax the user wants to take an action on.

The Telnys Programmable Fax API supports PDF files. To initiate sending the fax, we need to send the request to the Telnyx Programmable Fax API endpoint [https://api.telnyx.com/v2/faxes](https://api.telnyx.com/v2/faxes).

## Authentication

With the request we need to send additional parameters containing authentication information so Telnyx knows which account to send the fax from and information about the destination and file being sent.

HEADER
DESCRIPTION
media\_url
Authorization: Bearer YOUR\_API\_KEY
connection\_id
Authorization: Bearer YOUR\_API\_KEY
to
Authorization: Bearer YOUR\_API\_KEY
from
Authorization: Bearer YOUR\_API\_KEY
Authorization: Bearer
The prefix to your API V2 key created in Step 2.

## Available commands and their expected Webhooks

Telnyx sends webhooks to update on the status of Programmable Fax. Webhooks will also be sent in response to requests to list and delete faxes.

COMMAND
ASSOCIATED WEBHOOKS
Send a fax
fax.queued
fax.media.processed
fax.sending.started
fax.delivered
fax.failed

## Response when sending command

When you send a Programmable Fax API Command, you will immediately receive an http response. Responses include, but are not limited to:

HTTP STATUS CODE
MESSAGE
DESCRIPTION
202
OK
The request succeeded.
403
Forbidden
The request was valid, however the user is not authorized to perform this action.
404
Not Found
The requested resource could not be found.
422
Invalid Parameters
The request has invalid parameters.

## Example: Sending commands

To send a fax, send a POST request to the [https://api.telnyx.com/v2/faxes](https://api.telnyx.com/v2/faxes) endpoint as shown in the example below.

## WITH A API V2 KEY

```bash theme={null}
curl -X POST https://api.telnyx.com/v2/faxes \
--data-urlencode "media_url=https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf" \
--data-urlencode "connection_id=1232154810234" \
--data-urlencode "to=+13129457420" \
--data-urlencode "from=+19459457421" \
--header "Authorization: Bearer APIAuthKey_fromPortal"
```

After pasting the above content, Kindly check and remove any new line added

***

### Send a fax via API

> Source: [https://developers.telnyx.com/docs/programmable-fax/send-a-fax-api.md](https://developers.telnyx.com/docs/programmable-fax/send-a-fax-api.md)

The Telnyx Programmable Fax API lets you send, receive, and manage faxes through a set of easy-to-use HTTP endpoints.

In this guide, you'll learn how to send a fax using the Programmable Fax API in four simple steps.

## Step 1: Setting up with Telnyx

### Setup a Telnyx account, phone number, and programmable fax application

First, follow our [Quickstart](/docs/programmable-fax/quickstart) guide to create a Telnyx account, phone number, and Fax Application.

## Step 2: API authentication

> If you already have a Telnyx V2 API Authentication key, skip to Step 3.

1. In the Telnyx
   Mission Control Portal
   , in the left menu bar navigate to "
   API Keys
   ".
2. Ensure, API V2 is selected in the horizontal menu bar.
3. Click "Create API key"
4. Copy the API key and save it somewhere safe.

## Step 3: Send a PDF with the programmable fax API using curl

The Telnyx Programmable Fax API supports PDF files. To initiate sending a fax, we need to send the request to the Telnyx Programmable Fax API endpoint `https://api.telnyx.com/v2/faxes`.

We need to send additional parameters containing authentication information with the request, so Telnyx knows which account to send the fax from and information about the destination and file being sent.

Header
Description
media\_url
The URL of the PDF used for the fax's media.
connection\_id
The app ID or connection ID to send the fax with.
to
The fax enabled phone number (in E.164 format), or SIP URI, the fax will be sent to.
from
The phone number, in E.164 format, the fax will be sent from.
Authorizaton: Bearer
The prefix to your API V2 key created in Step 2.

Now that we know what we need to include in our request, we can use a number of different methods to structure and send it. In this example, we are going to use curl straight from the command line. You can also use a client such as
Postman
to structure your request.

```bash theme={null}
curl -X POST https://api.telnyx.com/v2/faxes \
--data-urlencode "media_url=https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf" \
--data-urlencode "connection_id=1232154810234" \
--data-urlencode "to=+13129457420" \
--data-urlencode "from=+19459457421" \
--header "Authorization: Bearer APIAuthKey_fromPortal"
```

After pasting the above content, Kindly check and remove any new line added

Simply copy the above code into your favorite text editor, paste in your parameters from the table in place of the existing data, and execute the command.

## Step 4: Verify HTTP response and receive webhooks

If you have successfully structured your command and the fax has begun sending, the Programmable Fax API will respond with HTTP 202.

If you do not receive a HTTP 202 response, double-check your request and try again. Explanations of other response codes can be found in our [API reference](/docs/programmable-fax/sending-commands#response-when-sending-command).

Once the request to send the fax has been successfullly received by Telnyx, you should begin receiving a series of webhooks to the URL that you specified in your Fax Application.

The webhooks you should receive are:

* `fax.queued`
* `fax.media.processed`
* `fax.sending.started`
* `fax.delivered`
* `fax.failed`

That's it! Once you've received a `fax.delivered` webhook, your fax has been delivered to its destinaion.

## Webhook examples

#### On successful delivery

```json theme={null}
{
  "event_type": "fax.delivered",
  "id": "3320554f-6b74-4138-a74b-a1e2ec7eaf8b",
  "occurred_at": "2022-01-07T10:01:43.677850Z",
  "payload": {
    "call_duration_secs": 79,
    "connection_id": "1232154810234",
    "direction": "outbound",
    "fax_id": "c62be5bc-9b13-4b6c-abda-34dd8b541287",
    "from": "+19459457421",
    "original_media_url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
    "page_count": 1,
    "status": "delivered",
    "to": "+13129457420",
    "user_id": "bdaa1f9f-1018-4156-867d-6c4ac9f556eb"
  }
}
```

After pasting the above content, Kindly check and remove any new line added

#### On failed delivery

```json theme={null}
{
  "event_type": "fax.failed",
  "id": "d906ecda-db21-428e-9ca0-74dae7e7c144",
  "occurred_at": "2022-01-05T22:23:46.888808Z",
  "payload": {
    "connection_id": "1232154810234",
    "direction": "outbound",
    "failure_reason": "user_busy",
    "fax_id": "f7b303ed-674c-4962-951b-848380510893",
    "from": "+19459457421",
    "original_media_url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
    "status": "failed",
    "to": "+13129457420",
    "user_id": "417b0cc2-39e0-4ab9-b116-e56543649aa9"
  }
}
```

After pasting the above content, Kindly check and remove any new line added

#### Possible failure reasons

Inspect the `failure_reason` field in webhook's payload to debug failed deliveries of your faxes. The possible failure reasons are:

* `account_disabled`
* `connection_channel_limit_exceeded`
* `destination_invalid`
* `destination_not_in_countries_whitelist`
* `destination_not_in_service_plan`
* `destination_unreachable`
* `fax_initial_communication_timeout`
* `fax_signaling_error`
* `invalid_ecm_response_from_receiver`
* `no_outbound_profile`
* `outbound_profile_channel_limit_exceeded`
* `outbound_profile_daily_spend_limit_exceeded`
* `receiver_call_dropped`
* `receiver_communication_error`
* `receiver_decline`
* `receiver_incompatible_destination`
* `receiver_invalid_number_format`
* `receiver_no_answer`
* `receiver_no_response`
* `receiver_recovery_on_timer_expire`
* `receiver_unallocated_number`
* `service_unavailable`
* `user_busy`
* `user_channel_limit_exceeded`

## Where to next?

Continue to our next tutorial to learn how to [receive inbound faxes](/docs/programmable-fax/receive-a-fax-api) via API.

***

### Receive a fax via API

> Source: [https://developers.telnyx.com/docs/programmable-fax/receive-a-fax-api.md](https://developers.telnyx.com/docs/programmable-fax/receive-a-fax-api.md)

The Telnyx Programmable Fax API lets you send, receive and manage faxes through a set of easy-to-use HTTP endpoints.

In this guide, you'll learn how to handle receiving a fax using the Programmable Fax API.

## Step 1: Setup with Telnyx

### Setup a Telnyx account, phone number, and programmable fax application

First, follow our [Quickstart](/docs/programmable-fax/quickstart) guide to create a Telnyx account, phone number, and Fax Application.

The phone number that you select and associate with the Programmable Fax Application will receive incoming fax calls. You can also port an existing number to Telnyx and use it for Programmable Fax.

### Step 2: Receiving Webhooks

In order for the webhooks in this tutorial to work, Telnyx must be able to send your web application an HTTP request over the Internet. That means your application needs to have a URL or IP address that Telnyx can reach. Telnyx sends webhooks to the URL or IP address to notify your application of incoming faxes.

For the purpose of this tutorial, we're using
ngrok
, a popular tunneling tool used to expose a locally running application to the internet. ngrok gives you a public URL for a local port on your development machine, which you can use to configure your Telnyx webhooks as described above.

Download and install ngrok, then use it at the command line to create a tunnel to whatever port your web application is running on. For example, this command will create a public URL for a web application listening on port 3000.

```bash theme={null}
ngrok http 3000
```

After executing that command, you will see that ngrok has given your application a public URL that you can use in your webhook connection configuration in the
Telnyx Mission Control Portal
.

<img src="https://mintcdn.com/telnyx/M104dP2YWeqFiyN4/img/twiml-conferencing-3.png?fit=max&auto=format&n=M104dP2YWeqFiyN4&q=85&s=a03fd275eee206cd8f17ecba9b27987f" alt="Send and receive fax using Telnyx Programmable Fax API" width="657" height="218" data-path="img/twiml-conferencing-3.png" />

Grab your ngrok public URL and head back to the Programmable Fax Application you configured earlier. Now in the field under "Send a webhook to the URL" enter your new ngrok URL from either of the "Forwarding" URLs ngrok provided us with depending on if you want to use HTTP or HTTPS.

You're now all set up to receive webhooks for events related to inbound faxes. If you use the same Programmable Fax Application for sending faxes, you will receive events to the same ngrok URL you just created.

### Example Webhooks

If you have set everything up correctly, any time an inbound fax is received you can expect to receive the following webhooks:

Webhook Name
Description
fax.receiving.started
The fax has begun transmitting to Telnyx successfully.
fax.media.processing.started
Telnyx has received the fax and is generating the digital PDF file.
fax.received
The PDF has been generated and the file is ready to be downloaded.
fax.failed
Transmission of the fax failed. Check the \<code>failure\_reason\</code> for more details.

### Fax has begun transmitting to Telnyx

```json theme={null}
{
  "data": {
    "event_type": "fax.receiving.started",
    "id": "bc004786-f166-4dd3-8c5d-737990b501bc",
    "occurred_at": "2020-08-27T16:33:29.684247Z",
    "payload": {
      "connection_id": "1447842681660114324",
      "direction": "inbound",
      "fax_id": "9fbc3f0d-5495-42af-9a4e-c57a235d9182",
      "from": "+16132484872",
      "status": "receiving",
      "to": "+17733372863",
      "user_id": "19a75cea-02c6-4b9a-84fa-c9bc8341feb8",
      "caller_id": "+16132484872"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://1a3097.ngrok.io/"
  }
}
```

### Fax transmission is complete and Telnyx is converting to PDF

```json theme={null}
{
  "data": {
    "event_type": "fax.media.processing.started",
    "id": "35e33b02-6365-47d0-93b7-3bfec97c467e",
    "occurred_at": "2020-08-27T16:33:33.175396Z",
    "payload": {
      "connection_id": "1447842681660114324",
      "direction": "inbound",
      "fax_id": "f72eebbe-f9b6-4f0f-b652-03e742e110d5",
      "from": "+16132484850",
      "status": "media.processing",
      "page_count": 2,
      "to": "+17733372863",
      "user_id": "19a75cea-02c6-4b9a-84fa-c9bc8341feb8",
      "caller_id": "+16132484872"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://1a3097.ngrok.io/"
  }
}
```

### PDF has been generated and is ready for download

The media\_url field contains a signed AWS link to a PDF of the received fax. This URL is valid for 10 minutes before the file is no longer accessible so be sure to download the file if you wish to keep it!

```json theme={null}
{
  "data": {
    "event_type": "fax.received",
    "id": "4844b70c-3c6c-4c3a-ba2e-e4c785f02d24",
    "occurred_at": "2020-08-27T16:33:36.843054Z",
    "payload": {
      "call_duration_secs": 50,
      "connection_id": "1447842681660114324",
      "direction": "inbound",
      "fax_id": "f72eebbe-f9b6-4f0f-b652-03e742e110d5",
      "from": "+16132484850",
      "media_url": "https://s3.amazonaws.com/faxes-prod/19a75cea-02c6-4b9a-84fa-c9bc8341feb8/f72eebbe-f9b6-4f0f-b652-03e742e110d5.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...%2F20200827%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20200827T163336Z&X-Amz-Expires=7200&X-Amz-SignedHeaders=host&X-Amz-Signature=...",
      "page_count": 2,
      "partial_content": false,
      "status": "received",
      "to": "+17733372863",
      "user_id": "19a75cea-02c6-4b9a-84fa-c9bc8341feb8",
      "caller_id": "+16132484872"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://1a3097.ngrok.io/"
  }
}
```

### Uh oh, something has gone wrong and the fax failed

Inbound faxes can fail for a variety of reasons. Some of the most common reasons are that the sending party hung up before the fax was finished transmitting or didn't send anything at all.

```json theme={null}
{
  "data": {
    "event_type": "fax.failed",
    "id": "1a7405a6-696c-4369-a0b1-168e4bb7e22c",
    "occurred_at": "2020-08-27T16:17:51.844250Z",
    "payload": {
      "connection_id": "1447842681660114324",
      "direction": "inbound",
      "failure_reason": "sender_call_dropped",
      "fax_id": "181533f3-b0b8-4bcd-ab01-b33cd8698508",
      "from": "+16617480240",
      "status": "failed",
      "to": "+17733372863",
      "user_id": "19a75cea-02c6-4b9a-84fa-c9bc8341feb8",
      "caller_id": "+16132484872"
    },
    "record_type": "event"
  },
  "meta": {
    "attempt": 1,
    "delivered_to": "https://1a3097.ngrok.io/"
  }
}
```

### Where to next?

Go back to our previous tutorial to learn how to [send outbound faxes](/docs/programmable-fax/send-a-fax-api) via API.

***

### Email to fax

> Source: [https://developers.telnyx.com/docs/programmable-fax/email-to-fax.md](https://developers.telnyx.com/docs/programmable-fax/email-to-fax.md)

**⏱ 60 minutes build time.**

\_\_🧰 Clone the sample application from our
GitHub repo
\_\_

In this tutorial, you'll learn how to use the Telnyx Fax API to receieve faxes to your email in Python.

Our Programmable Fax API, combined with our Numbers API, provides everything you need to build a robust call tracking application:

The Numbers API enables you to search the Telnyx phone number inventory in real time; filtering by Area Code, City/State, and more to find the perfect local number for your use-case.
Call Control enables you to quickly setup dynamic forwarding numbers, toggle dual-channel recording, join/leave dynamic conferences, and pull post-call analytics.
By following this tutorial, you'll be able to:

> 1. Configure a Telnyx portal account.
> 2. Set up a Telnyx Fax profile and an outbound voice profile.
> 3. How to send a fax to your email using Telnyx.
> 4. How to send a fax using your email and to Telnyx Fax profile.

## What you'll need to get started with email to fax

1. A Telnyx account- take a minute to
   sign up
   to our self-service portal.
2. A Telnyx phone number that's enabled with a
   Telnyx Fax Appliction
   and a Telnyx
   Outbound Voice profile
   .
3. Ability to receive webhooks (with something like [ngrok](/development/development-tools/ngrok-setup/index#ngrok "ngrok"))
4. [Python and PIP](/development/sdk/python "Python and PIP") installed
5. An AWS Account setup with proper profiles and groups with IAM for S3. Check out the
   Quickstart
   for more information.
6. Finally you'll need a
   Mailgun account
   . If you're planning on using this guide to build an email to fax application you'll need an account with the ability to setup
   inbound routes
   .

### Create a Telnyx Mission Control Portal account

To get started, you'll need to
create an account
. Verify your email address and you can log into the
Mission Control Portal
to get started.

### Usage

The following environmental variables need to be set:

Variable
Description
TELNYX\_API\_KEY
Your Telnyx API Key
TELNYX\_PUBLIC\_KEY
Telnyx Public Key
TELNYX\_S3\_BUCKET
The name of the bucket to upload the media attachments
TELNYX\_FAX\_CONNECTION\_ID
The connection ID for your Fax Applications
MAILGUN\_API\_KEY
Your Mailgun API Key
MAILGUN\_DOMAIN
Your Mailgun Domain.
PORT
Defaults to 8000 The port the app will be served

### .env file

This app uses the excellent python-dotenv package to manage environment variables.

Make a copy of .env.sample and save as .env and update the variables to match your creds.

TELNYX\_PUBLIC\_KEY="+kWXUag92mcUMFQopVlff7ctD/m2S/IoXv+AlI1/5a0="
TELNYX\_API\_KEY="KEYI"
TELNYX\_S3\_BUCKET=telnyx-mms-demo
TELNYX\_FAX\_CONNECTION\_ID=36092346987
MAILGUN\_API\_KEY="123-432-123"
MAILGUN\_DOMAIN="sandbox367c5ec1512d458e95f5e5c60f5fe97a.mailgun.org"
PORT=8000

### Callback URLs for Telnyx application

Callback Type
URL
Fax Callbacks
`&#123;ngrok-url&#125;/faxes`
Email Callbacks
`&#123;ngrok-url&#125;/email/inbound`

### Install

Run the following commands to get started:

\$ git clone [https://github.com/team-telnyx/demo-python-telnyx.git](https://github.com/team-telnyx/demo-python-telnyx.git)

### Ngrok

This application is served on the port defined in the runtime environment (or in the .env file). Be sure to launch ngrok for that port:

./ngrok http 8000

ngrok by @inconshreveable                                                                                                                               (Ctrl+C to quit)

Session Status                online
Account                       Little Bobby Tables (Plan: Free)
Version                       2.3.35
Region                        United States (us)
Web Interface                 [http://127.0.0.1:4040](http://127.0.0.1:4040)
Forwarding                    [http://your-url.ngrok.io](http://your-url.ngrok.io) -> [http://localhost:8000](http://localhost:8000)
Forwarding                    [https://your-url.ngrok.io](https://your-url.ngrok.io) -> [http://localhost:8000](http://localhost:8000)

Connections                   ttl     opn     rt1     rt5     p50     p90
0       0       0.00    0.00    0.00    0.00

At this point you can point your application to generated ngrok URL + path:

(Example: `http://&#123;your-url&#125;.ngrok.io/faxes`).

## Run

### High level code overview

#### Receiving fax, sending email

1. Receive the webhook from Telnyx indicating fax is incoming
2. We only only care about the fax.received webhook for inbound faxes
3. Extract the to/from and other information about the fax
4. Download the attachment and save locally
5. Lookup the association between phone\_number and email
6. Create and send an email via Mailgun with downloaded media as an attachment

#### Sending fax

1. Receive webhook from mailgun for incoming email
2. Extract the prefix of the email ([19198675309@MAILGUN\_DOMAIN.com](mailto:19198675309@MAILGUN_DOMAIN.com), we want 19198675309) and prepend the +
3. Lookup the association between email and phone\_number to determine the from phone number.
4. Save the first attachment locally
5. Upload the attachment to S3
6. Create and send a fax to the phone number extracted above

### Update "DB"

The app as provided uses a dumb-hard-coded database to minimize dependencies for the sake of examples. There is an in memory database defined at the top that associates an email to a Telnyx number.

```
    DB = [
{
    "email": "@telnyx.com",
    "phone_number": "+"
}
    ]
```

* phone\_number is a **Telnyx** phone number
* email is the email to associate with that phone number

#### Receiving faxes

```
{+19198675309} ==(faxes)==> {telnyx_phone_number} ==(emails)==> {email_as_defined}
```

#### Sending faxes

```
{email_as_defined} ==(emails)==> {destination_phone_number@MAILGUN_DOMAIN} ==(faxes)==> {destination_phone_number}
```

### Launch the app and update callbacks

Start the server python app.py

When you are able to run the server locally, the final step involves making your application accessible from the Internet. So far, we've set up a local web server. This is typically not accessible from the public internet, making testing inbound requests to web applications difficult.

The best workaround is a tunneling service. They come with client software that runs on your computer and opens an outgoing permanent connection to a publicly available server in a data center. Then, they assign a public URL (typically on a random or custom subdomain) on that server to your account. The public server acts as a proxy that accepts incoming connections to your URL, forwards (tunnels) them through the already established connection and sends them to the local web server as if they originated from the same machine. The most popular tunneling tool is ngrok.

Check out the [ngrok setup](/development/development-tools/ngrok-setup/index#ngrok "ngrok setup") walkthrough to set it up on your computer and start receiving webhooks from inbound faxes to your newly created application.

Once you've set up ngrok or another tunneling service you can add the public proxy URL to your Inbound Settings in the Mission Control Portal. To do this, click the edit symbol \[✎] next to your Fax Profile. In the "Inbound Settings" > "Webhook URL" field, paste the forwarding address from ngrok into the Webhook URL field. Add faxes to the end of the URL to direct the request to the webhook endpoint in your server.

For now you'll leave “Failover URL” blank, but if you'd like to have Telnyx resend the webhook in the case where sending to the Webhook URL fails, you can specify an alternate address in this field.

Once everything is setup, you should now be able to:

* Fax your phone number and receive an email
* Email `&#123;19198675309&#125;@domain.com` an attachment to send a fax to `&#123;19198675309&#125;`

## Fax follow-Ons

Now that you've successfully sent a fax to your email and phone number, you can explore more fax features and discover ideas to build new applications.

Our developer Slack community is full of Python developers like you - be sure to join to see what your fellow developers are building!

***

## API Reference (Fax)

### Programmable Fax Applications

* [List all Fax Applications](https://developers.telnyx.com/api-reference/programmable-fax-applications/list-all-fax-applications.md): This endpoint returns a list of your Fax Applications inside the 'data' attribute of the response. You can adjust which applications are listed by using filter…
* [Creates a Fax Application](https://developers.telnyx.com/api-reference/programmable-fax-applications/creates-a-fax-application.md): Creates a new Fax Application based on the parameters sent in the request. The application name and webhook URL are required. Once created, you can assign phon…
* [Retrieve a Fax Application](https://developers.telnyx.com/api-reference/programmable-fax-applications/retrieve-a-fax-application.md): Return the details of an existing Fax Application inside the 'data' attribute of the response.
* [Update a Fax Application](https://developers.telnyx.com/api-reference/programmable-fax-applications/update-a-fax-application.md): Updates settings of an existing Fax Application based on the parameters of the request.
* [Deletes a Fax Application](https://developers.telnyx.com/api-reference/programmable-fax-applications/deletes-a-fax-application.md): Permanently deletes a Fax Application. Deletion may be prevented if the application is in use by phone numbers.

### Programmable Fax Commands

* [View a list of faxes](https://developers.telnyx.com/api-reference/programmable-fax-commands/view-a-list-of-faxes.md)
* [Send a fax](https://developers.telnyx.com/api-reference/programmable-fax-commands/send-a-fax.md): Send a fax. Files have size limits and page count limit validations. If a file is bigger than 50MB or has more than 350 pages it will fail with \`file\_size\_limi…
* [View a fax](https://developers.telnyx.com/api-reference/programmable-fax-commands/view-a-fax.md)
* [Delete a fax](https://developers.telnyx.com/api-reference/programmable-fax-commands/delete-a-fax.md)
* [Cancel a fax](https://developers.telnyx.com/api-reference/programmable-fax-commands/cancel-a-fax.md): Cancel the outbound fax that is in one of the following states: `queued`, `media.processed`, `originated` or `sending`
* [Refresh a fax](https://developers.telnyx.com/api-reference/programmable-fax-commands/refresh-a-fax.md): Refreshes the inbound fax's media\_url when it has expired

### Callbacks

* [Fax Delivered](https://developers.telnyx.com/api-reference/callbacks/fax-delivered.md)
* [Fax Failed](https://developers.telnyx.com/api-reference/callbacks/fax-failed.md)
* [Fax Media Processed](https://developers.telnyx.com/api-reference/callbacks/fax-media-processed.md)
* [Fax Queued](https://developers.telnyx.com/api-reference/callbacks/fax-queued.md)
* [Fax Sending Started](https://developers.telnyx.com/api-reference/callbacks/fax-sending-started.md)
