Introduction

This document details how to programmatically interact with Fyn's API. This document is primarily aimed at developers.

Fyn has a RESTful API. Our API has predictable URLs, accepts JSON-encoded request bodies and in certain cases files, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs.

You can ask us questions about the API directly at developers@fyn.ai.

Not a developer?

We help our customers integrate our solution within their own tools. If you're looking for help with an integration, please contact us at sales@fyn.ai.

Authentication

Most routes of Fyn's API require you to be authenticated. You can view and manage your keys in the dashboard.

Your API keys carry many privileges, so be sure to keep them secure. Do not share your API keys in publicly accessible areas such as Github, client-side codes, and so forth.

Authentication to the API is performed via an Authorization header.

All requests must be made over HTTPS. Calls made over plain HTTP may fail.

API requests to routes that require authentication will fail if no authorization or an incorrect authorization header is passed.

Authentication request

curl -H "Authorization: Bearer ${YOUR_TOKEN}" https://api.fyn.ai/profile

Errors

Fyn uses conventional HTTP responses to indicate success or failure of an API request. In general, codes in the 2xx range indicate success, while codes in the 4xx range indicate errors caused by the sender of the request. Codes in the 5xx range indicate errors with Fyn's servers (these are rare).

Some 4xx errors can be handled programmatically using the ERROR_CODE key.

HTTP status code summary

200

Everything worked as expected.

400

The request was not accepted, often due to missing a required parameter.

401

The request was not authorized.

402

The request's parameters were correct but a payment is required.

404

The requested route doesn't exist.

429

Too many requests hit the API too quickly.

5xx

Something went wrong on Fyn's end.

Routes

extractions

A group of routes that allow you to extract information from documents.

Get an overview of extracted documents

This route gives you the status of all the documents you have sent to Fyn.

  • The created_at, updated_at and processed_at keys indicate when the document was created, updated and processed, in ISO 8601 format.
  • The document_id key of a successful response is the unique identifier of your document within our system. This key is required to get the results of the extraction.
  • The user_id key is your unique identifier within our system. This key is informative - you don't need to use it to get your results.
  • The document_stem and document_extension are the filename and extension of the file as you have sent them to us. You can send us document with identical filenames and extensions, which we will treat as different documents. However, identical documents (as determined by their Checksum) will not be re-treated.
  • The document_status key of a successful response indicates the processing status of the document. This value of this key can be processing, completed or error. Errors should be rare: this usually means something has gone wrong on our end. Documents that can not be fully treated (e.g. the language in the document is currently not supported) are also marked as completed. The reason why a file cannot be fully treated can be found in the detailed extraction results.
  • The is_corrected key indicates whether a correction was sent for a particular document.
Endpoints
GET/extractions/
headers
Authorizationstring
Required

An API key generated through your dashboard.

Authorization: Bearer ${YOUR_TOKEN_HERE}
args
limitint
Required

The maximum number of documents to list at once. Must be smaller or equal to 50 and larger than 0.

limit=10
offsetint

The number of documents to offset the request by.

offset=5
Code Example
const axios = require('axios')const auth_token = 'MY_PERSONAL_TOKEN' // replace with your tokenconst result = await axios({  method: 'get',  url:`https://api.fyn.ai/extractions/?limit=10`,  headers: {    'Authorization': `Bearer ${auth_token}`,  },})console.log(result)
Success Response
200
Your documents.
{
  "status": "success",
  "data": [
    {
      "created_at": "2020-01-01T12:12:12",
      "updated_at": "2020-01-01T12:12:12",
      "processed_at": "2020-01-01T12:12:12",
      "document_id": "4e5a6c56-33e1-4023-8510-d82d1cef1bbc",
      "user_id": "2f36cf5c-daee-11e9-8a34-2a2ae2dbcce4",
      "document_stem": "document_0",
      "document_extension": "pdf",
      "document_status": "completed",
      "is_corrected": false
    }
  ]
}
Error Response
400
A general error occurred.
{
  "status": "error",
  "message": "An error happened.",
  "error_code": "GENERAL_ERROR"
}
Error Response
401
An authorization error occurred.
{
  "status": "error",
  "message": "You don't have the proper authorization.",
  "error_code": "NOT_AUTHORIZED"
}

Delete one or several documents

This route allows you to delete one or several documents you have sent to Fyn.

Endpoints
DELETE/extractions/
headers
Authorizationstring
Required

An API key generated through your dashboard.

Authorization: Bearer ${YOUR_TOKEN_HERE}
args
document_iduuid
Required

The uuid of the document you want to delete.

document_id=4e5a6c56-33e1-4023-8510-d82d1cef1bbc
Code Example
const axios = require('axios')const auth_token = 'MY_PERSONAL_TOKEN' // replace with your tokenconst result = await axios({  method: 'delete',  url:`https://api.fyn.ai/extractions/?document_id=4e5a6c56-33e1-4023-8510-d82d1cef1bbc`,  headers: {    'Authorization': `Bearer ${auth_token}`,  },})console.log(result)
Success Response
200
Confirmation of the documents deletion.
{
  "status": "success",
  "message": "Documents deleted."
}
Error Response
400
A general error occurred.
{
  "status": "error",
  "message": "An error happened.",
  "error_code": "GENERAL_ERROR"
}
Error Response
401
An authorization error occurred.
{
  "status": "error",
  "message": "You don't have the proper authorization.",
  "error_code": "NOT_AUTHORIZED"
}

Extract information from a single document

This route allows you to post a document to be treated by Fyn.

The document_id key is the unique identifier used to get the extracted results.

Endpoints
POST/extractions/
headers
Authorizationstring
Required

An API key generated through your dashboard.

Authorization: Bearer ${YOUR_TOKEN_HERE}
body
filefile
Required

The file to be treated by Fyn. Currently only pdf is handled as file type.

Code Example
const axios = require('axios')const auth_token = 'MY_PERSONAL_TOKEN' // replace with your tokenconst form_data = new FormData()form_data.append('file' , fs.createReadStream('PATH_TO_FILE')const result = await axios({  method: 'post',  url:`https://api.fyn.ai/extractions/`,  headers: {    'Authorization': `Bearer ${auth_token}`,    'Content-Type': 'multipart/form-data',   },  data: form_data,})console.log(result)
Success Response
200
Confirmation of the upload.
{
  "status": "success",
  "message": "Your document is being treated.",
  "data": [
    {
      "document_id": "4e5a6c56-33e1-4023-8510-d82d1cef1bbc"
    }
  ]
}
Error Response
400
A general error occurred.
{
  "status": "error",
  "message": "An error happened.",
  "error_code": "GENERAL_ERROR"
}
Error Response
401
An authorization error occurred.
{
  "status": "error",
  "message": "You don't have the proper authorization.",
  "error_code": "NOT_AUTHORIZED"
}

Get the extracted information from a document

This route allows you to get the extraction results of a single document.

  • The document key contains information about the document you have sent to us, such as the page_count, the document_type, etc.
  • The checks key contains a number of checks that were run on the document and extracted data. If a document is not fully extracted, the reason why can usually be found in the checks.
  • The extraction key contains the information we managed to extract from your document. This key has 4 subkeys:
    • raw: the raw text we extracted from the invoice ("as is")
    • postprocessed: a processed form of the text we extracted from the document, coerced into the expected formats (e.g. dates formatted as dates)
    • augmented: identical to the postprocessed key, but augmented with external data (e.g. finding the address of a supplier based on their VAT number)
    • corrected: the corrected extraction you have optionally provided to us (see the corrections route).
Endpoints
GET/extractions/<document_id>
headers
Authorizationstring
Required

An API key generated through your dashboard.

Authorization: Bearer ${YOUR_TOKEN_HERE}
Code Example
const axios = require('axios')const auth_token = 'MY_PERSONAL_TOKEN' // replace with your tokenconst document_id = 'MY_DOCUMENT_ID' // replace with your document_idconst result = await axios({  method: 'get',  url:`https://api.fyn.ai/extractions/${document_id}`,  headers: {    'Authorization': `Bearer ${auth_token}`,  },})console.log(result)
Success Response
200
Extracted data if the processing is completed and without results if still processing. See document_status.
{
  "status": "success",
  "data": {
    "document": {
      "document_id": "4e5a6c56-33e1-4023-8510-d82d1cef1bbc",
      "file_stem": "document_0",
      "file_extension": "pdf",
      "file_size_kb": 876543,
      "page_count": 2,
      "document_type": "invoice",
      "language": "fr"
    },
    "extraction": {
      "raw": {
        "LegalMonetoryTotal": {
          "PayableAmount": "100,00"
        },
        "TaxTotal": {
          "TaxAmount": "EUR21,00"
        },
        "DueDate": "1st Jan 2021",
        "other": "..."
      },
      "postprocessed": {
        "LegalMonetoryTotal": {
          "PayableAmount": 100
        },
        "TaxTotal": {
          "TaxAmount": 21
        },
        "DueDate": 1609459200,
        "other": "..."
      },
      "other": "..."
    },
    "checks": [
      {
        "check_type": "DOCUMENT_NOT_TOO_LARGE",
        "passed": true,
        "check_key": "document"
      },
      {
        "check_type": "DOCUMENT_TYPE_SUPPORTED",
        "passed": true,
        "check_key": "document"
      },
      {
        "check_type": "DOCUMENT_READABLE",
        "passed": true,
        "check_key": "document"
      }
    ]
  }
}
Error Response
400
A general error occurred.
{
  "status": "error",
  "message": "An error happened.",
  "error_code": "GENERAL_ERROR"
}
Error Response
401
An authorization error occurred.
{
  "status": "error",
  "message": "You don't have the proper authorization.",
  "error_code": "NOT_AUTHORIZED"
}

corrections

A group of routes that allow you to submit corrections of extracted information.

While we strive to extract information without errors, we cannot guarantee that there won't be any error in our extraction process. By submitting a correction, you help us to improve our extraction process, and we'll reimburse you for any cost that you may have had for extracting information for the document that contained errors.

The corrections you provide to us should be factual, and only contain information that is available in the document. With "factual", we mean that the correction should actually correct the extraction we provide to you. With "available in the document", we mean that the data in the correction cannot originate from anywhere else than the textual information in the document.

Please be aware that corrections that are either non-factual, or contain information that is not available in the document risk being rejected. For example, if you submit a document that contains a typo in a non-formatted field (such as a name), our engine will likely copy this typo "as is". Rather than providing a correction that fixes this typo, we recommend that you ask your supplier to correct the mistake on their end.

How are corrections validated?
Most corrections are auto-checked and validated. Corrections that are not accepted have been checked by a human - you will find the explanation for a rejection in a correction in the payload. If you feel we made a mistake with a rejection of a correction, please reach out to us at support@fyn.ai - we're happy to resolve these issues!

Submit a correction

This route allows you to submit a correction. Fyn will only store the last correction submitted.

The payload should hold all the provided keys from the data.result.extraction.postprocessed element of extracted information.

Endpoints
POST/corrections/<document_id>
headers
Authorizationstring
Required

An API key generated through your dashboard.

Authorization: Bearer ${YOUR_TOKEN_HERE}
body
jsonjson
Required

The json file containing the corrections.

{ "corrected": { "LegalMonetoryTotal": { "PayableAmount": 120 }, "TaxTotal":[ { "TaxAmount": 10.00 } ], "IssueDate": "31/12/2019", "DueDate": "31/01/2020", "PaymentTerms": [ { "InvoicingPartyReference": "123456789" } ], "AccountingSupplierParty": { "Party": { "PartyName": { "Name": "Kantify" }, "PartyTaxScheme": { "CompanyID": "BE 0628 692 731" }, "PostalAddress": { "StreetName": "Rue Borrens 51", "PostalZone": "B-1050", "CityName": "Bruxelles" } } }, "AccountingCustomerParty": { "Party": { "PartyName": { "Name": "Kantify" }, "PartyTaxScheme": { "CompanyID": "BE 0628 692 731" }, "PostalAddress": { "StreetName": "Rue Borrens 51", "PostalZone": "B-1050", "CityName": "Bruxelles" } } } } }
Code Example
const axios = require('axios')const auth_token = 'MY_PERSONAL_TOKEN' // replace with your tokenconst document_id = 'MY_DOCUMENT_ID' // replace with your document_idconst data = { "my_data": "here" } // replace with your dataconst result = await axios({  method: 'post',  url:`https://api.fyn.ai/corrections/${document_id}`,  headers: {    'Authorization': `Bearer ${auth_token}`,  },  data: data,})console.log(result)
Success Response
200
Your correction.
{
  "status": "success",
  "message": "Correction submitted with success."
}
Error Response
400
A general error occurred.
{
  "status": "error",
  "message": "An error happened.",
  "error_code": "GENERAL_ERROR"
}
Error Response
401
An authorization error occurred.
{
  "status": "error",
  "message": "You don't have the proper authorization.",
  "error_code": "NOT_AUTHORIZED"
}
Error Response
422
The json data isn't properly formatted.
{
  "status": "error",
  "message": "A <ubl_field> object is malformed.",
  "error_code": "WRONG_DATA_FORMAT"
}