> For the complete documentation index, see [llms.txt](https://typless.gitbook.io/typlessapi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://typless.gitbook.io/typlessapi/typless/data-extraction/asynchronous-extraction.md).

# Asynchronous extraction

Most of the time, processing of the documents is not time critical.\
That is why we also provide an asynchronous endpoint for processing the documents.\
Currently, the processing is handled with the *process-poll* method, meaning you will have to check on intervals if the document processing has finished.

{% hint style="info" %}
**📘&#x20;**<mark style="color:blue;">**Use webhooks to receive a notification when data extraction is finished**</mark>

To optimize the asynchronous document processing, implement webhooks to never poll for data again!\
Check out the [Webhook](/typlessapi/typless-hub/webhooks.md) section on how to get started.
{% endhint %}

## Sample code for async extraction

The request for asynchronous processing is the same as the synchronous extract data request; the only difference is that you will immediately get the response with the **extraction\_id** of the process.\
You will then use this **extraction\_id** to poll for the status and results of the extraction.

You can try out the async extraction with the following sample code - there are currently only examples in Python; other languages will be added soon.

<details>

<summary><strong>1 Open file as base64 string</strong> <em><mark style="color:green;">(Lines 4-6)</mark></em></summary>

Open the file in binary mode and correctly decode it into a base64 string.\
Make sure that your file is in the same directory as the script.

</details>

<details>

<summary><strong>2 Create payload</strong> <em><mark style="color:green;">(Lines 8-12)</mark></em></summary>

Create request payload with all the required parameters:

* file
* file\_name
* document\_type\_name<br>

</details>

<details>

<summary><strong>3 Specify headers</strong> <em><mark style="color:green;">(Lines 16-20)</mark></em></summary>

Make sure that the Content-Type is set as application/json.

</details>

<details>

<summary><strong>4 Authorize with your API key</strong> <em><mark style="color:green;">(Line 19)</mark></em></summary>

You can get your API key at <https://app.typless.com/settings/profile>

</details>

<details>

<summary><strong>5 Execute the request</strong> <em><mark style="color:green;">(Lines 22-24)</mark></em></summary>

Send the request and wait for the response.

</details>

{% tabs %}
{% tab title="Python" %}
{% code lineNumbers="true" %}

```python
import requests
import base64

file_name = 'name_of_your_document.pdf'
with open(file_name, 'rb') as file:
    base64_data = base64.b64encode(file.read()).decode('utf-8')

payload = {
    "file": base64_data,
    "file_name": file_name,
    "document_type_name": "line-item-invoice"
}

url = "https://developers.typless.com/api/extract-data-async"

headers = {
    "Accept": "application/json",
    "Content-Type": "application/json",
    "Authorization": "<<apiKey>>"
}

response = requests.request("POST", url, json=payload, headers=headers)

print(response.json())
```

{% endcode %}
{% endtab %}
{% endtabs %}

If the process trigger was successful, you will get a HTTP 202 Accepted response with a body that will contain the **extraction\_id** of the asynchronous process.

{% tabs %}
{% tab title="Asynchronous process example response" %}
{% code lineNumbers="true" %}

```json
{
    "extraction_id": "0d14338251a6db69bfec36face27f7edcab7322"
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

To poll the data, you can then use the **extraction\_id** from the response&#x20;

<details>

<summary><strong>1 Authorize with your API key</strong> <em><mark style="color:green;">(Line 7)</mark></em></summary>

You can get your API key at <https://app.typless.com/settings/profile>

</details>

<details>

<summary><strong>2 Pass the extraction_id to query params</strong> <em><mark style="color:green;">(Line 5)</mark></em></summary>

Pass the extraction\_id of the process you got from the /extract-data-async endpoint and pass it as a query parameter **extraction\_id**

</details>

<details>

<summary><strong>3 Execute the request</strong> <em><mark style="color:green;">(Line 9)</mark></em></summary>

Execute the request and parse the response.

</details>

{% tabs %}
{% tab title="Python" %}
{% code lineNumbers="true" %}

```python
import requests

url = "https://developers.typless.com/api/get-extraction-data"

payload = {'extraction_id': 'your-extraction-id'}

headers = {"Authorization": "<<apiKey>>"}

response = requests.request("GET", url, headers=headers, params=payload)

print(response.json())
```

{% endcode %}
{% endtab %}
{% endtabs %}

You will always get a successful response from the poll endpoint (if a catastrophe didn't happen!)\
The polled data response will always have the same format with the following properties:

* **error**
* **result**
* **status**

Example:

{% tabs %}
{% tab title="JSON" %}
{% code lineNumbers="true" %}

```json
{
  "error": {},
  "result": {
    "customer": "customer-id",
    "extracted_fields": [
      {
        "data_type": "AUTHOR",
        "name": "supplier_name",
        "values": [
          {
            "confidence_score": 0.958,
            "height": -1,
            "page_number": -1,
            "value": "ScaleGrid",
            "width": -1,
            "x": -1,
            "y": -1
          }
        ]
      }, ...
    ],
    "file_name": "invoice.pdf",
    "line_items": [],
    "object_id": "0d143385c4fb3ec7b73256be40c4ce02b01bf097",
    "vat_rates": []
  },
  "status": "SUCCESS"
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

The **error** property will include any errors that might occur during the processing part. Most errors will be related to the input file if it was not valid. The errors will have the standard error format, which also occurs on all the other endpoints with properties:

* **code**
* **message**
* **details**

The **result** property will be an empty object if the processing was not finished.\
After the process is completed, it will include the results of the extraction in the same format as the synchronous endpoint. You can read more about the response [here](/typlessapi/typless/data-extraction.md).

The **status** property will include the current status of the process. It has 4 predefined states:

* *IN\_PROGRESS*
* *SUCCESS*
* *ERROR*
* *EXPIRED*

{% hint style="info" %}
**📘&#x20;**<mark style="color:blue;">**EXPIRED status**</mark>

The process gets an EXPIRED status 48 hours after the process has finished.\
This means that you have 48 hours to poll the data and access the results. Afterwards, the data will be deleted.
{% endhint %}

## Retrieving results using poll queue

Alternatively, you may want to periodically check for invoices that have finished extraction, and collectively get their results. This is where our ***/awaiting-poll*** endpoint comes in handy.&#x20;

For this flow, you do not need to save the extraction IDs. It suffices to periodically call the endpoint like this:

<details>

<summary><strong>1 Set the poll queue endpoint</strong> <em><mark style="color:green;">(Line 3)</mark></em></summary>

This is the `/awaiting-poll` endpoint, which returns a list of extraction IDs that are ready.\
You don’t need to save or track IDs individually.

</details>

<details>

<summary><strong>2 Add the customer filter</strong> <em><mark style="color:green;">(</mark><mark style="color:green;"><strong>Line 5</strong></mark><mark style="color:green;">)</mark></em></summary>

Use `customer`  filter if you are already using it for extraction, to differentiate between different companies that are using the same API key.

</details>

<details>

<summary><strong>3 Authorize the request</strong> <em><mark style="color:green;">(</mark><mark style="color:green;"><strong>Line 7</strong></mark><mark style="color:green;">)</mark></em></summary>

Insert your API key into the `Authorization` header.\
You can find it in your Typless profile settings.

</details>

<details>

<summary><strong>4 Execute the poll request</strong> <em><mark style="color:green;">(Line 9)</mark></em></summary>

Send a `GET` Request to retrieve all extraction IDs that are ready.\
Each ID in the response corresponds to a document that has finished processing.

</details>

{% tabs %}
{% tab title="Python" %}
{% code lineNumbers="true" %}

```python
import requests

url = "https://developers.typless.com/api/v1/awaiting-poll"

payload = {'customer': 'customer-id'}

headers = {"Authorization": "<<apiKey>>"}

response = requests.request("GET", url, headers=headers, params=payload)

print(response.json())
```

{% endcode %}
{% endtab %}
{% endtabs %}

If you used the `customer` field during extraction to differentiate between companies sharing the same API key, make sure to use the same customer ID here. Otherwise, including an incorrect or mismatched customer ID will result in an empty response — in that case, it's best to omit the field entirely.

You will get a response like this:

{% tabs %}
{% tab title="JSON" %}
{% code lineNumbers="true" %}

```json
{
  "extraction_ids": ['0d143385c4fb3ec7b73256be40c4ce02b01bf097',
                     '0d143385c4fb3e48341eb123f973eabc23111322']
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

Invoices with these extraction IDs have finished processing. We can then poll the results similarly to what we did earlier:

<details>

<summary><strong>1 Set the result retrieval endpoint</strong> <em><mark style="color:green;"><strong>(Line 3)</strong></mark></em></summary>

Use the `/get-extraction-data` endpoint to retrieve results for each ID returned earlier.

</details>

<details>

<summary><strong>2 Authorize again</strong> <em><mark style="color:green;">(Line 4)</mark></em></summary>

Use the same API key in the `Authorization` header.

</details>

<details>

<summary><strong>3 Loop through each extraction ID</strong> <em><mark style="color:green;">(</mark><mark style="color:green;"><strong>Line 6</strong></mark><mark style="color:green;">)</mark></em></summary>

Iterate over the list of `extraction_ids` returned by `/awaiting-poll`.

</details>

<details>

<summary><strong>4 Execute individual requests</strong> <em><mark style="color:green;">(</mark><mark style="color:green;"><strong>Line 8</strong></mark><mark style="color:green;">)</mark></em></summary>

For each ID, send a `GET` request to retrieve the result.\
You’ll receive the document's extracted content and status.

</details>

{% tabs %}
{% tab title="Python" %}

<pre class="language-python" data-line-numbers><code class="lang-python">import requests

url = "https://developers.typless.com/api/get-extraction-data"
headers = {"Authorization": "&#x3C;&#x3C;apiKey>>"}

for extraction_id in extraction_ids:
    payload = {'extraction_id': extraction_id}
<strong>    response = requests.request("GET", url, headers=headers, params=payload)
</strong>    print(response.json())
</code></pre>

{% endtab %}
{% endtabs %}

The response format is, of course, in the same format as it was mentioned earlier. Note that documents obtained in this flow can only have two response states:

*✅ SUCCESS*

*❌ ERROR*

Documents in progress and expired documents will not be included in the `/awaiting-poll` response.&#x20;
