Integration API Reference

Every integration API endpoint: authentication, parameters, responses, and error codes.

Every endpoint of the Foxello integration API - the API behind the Zapier app, the n8n node, and your own HTTP steps. For setting up integrations and connecting your tool, see Zapier and n8n.

Basics

Base URL: https://api.foxello.com/api/v1

Authentication: send the integration's connection key with every request:

Authorization: Bearer fxk_...

Create a connection key under Integrations in the sidebar (Owners and Admins). A key only reaches the workflows that selected its integration as their import method or export destination.

Format: requests and responses are JSON unless noted. Dates are ISO 8601 in UTC, for example 2026-10-12T10:00:00.000Z.

Rate limit: 300 requests per minute per connection key. Above that, the API answers 429 with a Retry-After header (seconds to wait).

Plans: the integration API is available on every plan. Excel results (format=xlsx) need the Growth or Scale plan.

Errors

Errors are returned with an HTTP status and a JSON body:

{
  "message": "Invalid or revoked connection key.",
  "code": "API-KEY-02",
  "status": 401
}

Errors every endpoint can return:

  • 401 API-KEY-01 - no connection key was sent.
  • 401 API-KEY-02 - the connection key is invalid, regenerated, or its integration was removed.
  • 403 API-PLAN-01 - integrations are not available for the account's subscription.
  • 429 SEC-RATE-01 - rate limit reached. Retry after the Retry-After seconds.

Endpoint-specific errors are listed with each endpoint.

Connection

Test the connection

GET /me

Returns the account and integration the connection key belongs to.

Response 200:

{
  "accountId": "6a1f2763e4b82c58360f9700",
  "accountName": "Acme Logistics",
  "integration": {
    "id": "6a1f2763e4b82c58360f9701",
    "name": "Accounts payable Zaps",
    "type": "zapier"
  }
}

integration.type is zapier or n8n.

Workflows

List workflows

GET /workflows

Lists the workflows connected to this integration.

Query parameters:

  • purpose (optional) - import returns workflows that accept documents from this integration; export returns workflows that send their results to it. Leave it out to get both.

Response 200:

[
  {
    "id": "6a1f2763e4b82c58360f9702",
    "name": "Invoices",
    "acceptsDocuments": true,
    "sendsResults": true
  }
]
  • acceptsDocuments - documents can be sent to this workflow with this connection key.
  • sendsResults - this workflow's results are sent to this integration.

List the fields a workflow extracts

GET /workflows/{workflowId}/fields

The fields each document type of the workflow returns, in the same docType / attribute structure as a document's fields. Use it to map fields before any document has been processed.

Response 200:

{
  "workflowId": "6a1f2763e4b82c58360f9702",
  "docTypes": [
    {
      "docType": "invoice",
      "fields": [
        {
          "attribute": "InvoiceTotal",
          "type": "currency",
          "description": "Total amount due",
          "example": "1,250.00",
          "fields": []
        },
        {
          "attribute": "Items",
          "type": "array",
          "fields": [
            { "attribute": "Description", "type": "string", "fields": [] },
            { "attribute": "Amount", "type": "currency", "fields": [] }
          ]
        }
      ]
    }
  ]
}
  • fields inside a field holds its sub-fields, for example the columns of a line-item table.
  • description and example are present when the workflow defines them.
  • docTypes is empty when the workflow only reads text.

Errors:

  • 404 WF-NF-01 - the workflow does not exist or is not connected to this integration.

Sending documents

Supported file types are PDF, JPG, JPEG, and PNG, unless the workflow allows fewer. The file type is checked from the file's content, not only its name.

Send a document

POST /workflows/{workflowId}/documents

Sends one document to the workflow for processing. Send either:

  • a file as multipart/form-data in the field file - up to 5 MB, or
  • JSON { "url": "https://..." } - Foxello downloads the file from the link, up to 100 MB. Redirects are followed. The link must be a public address.

For files over 5 MB that you have as bytes rather than a link, use the upload URL flow.

Headers:

  • Idempotency-Key (optional) - a unique value per document, 1 to 255 visible ASCII characters without spaces, for example your run or record ID. Sending the same key again within 24 hours returns the document created by the first request instead of creating a second one. A key belongs to one workflow.

Response 202: the new document. Processing continues in the background.

{
  "id": "6a1f2763e4b82c58360f9703",
  "name": "invoice-1042.pdf",
  "status": "pending",
  "workflowId": "6a1f2763e4b82c58360f9702",
  "workflowName": "Invoices",
  "pageCount": 0,
  "confidenceScore": 0,
  "createdAt": "2026-10-12T10:00:00.000Z",
  "updatedAt": "2026-10-12T10:00:00.000Z"
}

Errors:

  • 400 API-FILE-01 - no file and no URL was sent.
  • 400 API-FILE-02 - the file type is not allowed for this workflow.
  • 400 API-FILE-03 - the URL is invalid or not allowed.
  • 400 API-FILE-04 - the file could not be downloaded from the URL.
  • 400 API-FILE-05 - the file type could not be recognized from its content.
  • 400 API-UPLOAD-03 - the workflow does not accept documents from this integration.
  • 400 API-UPLOAD-04 - the Idempotency-Key header is invalid.
  • 400 API-UPLOAD-05 - the Idempotency-Key was already used for another workflow.
  • 404 WF-NF-01 - the workflow does not exist.
  • 409 API-UPLOAD-06 - a request with the same Idempotency-Key is still being received. Retry in a minute.
  • 413 FILE-UP-SIZE-01 - the file is larger than the limit.

Upload a large file

Three steps for files up to 100 MB that you have as bytes.

1. Request an upload URL

POST /workflows/{workflowId}/documents/uploads

Body:

{
  "fileName": "contract-scan.pdf",
  "fileSize": 48234112
}
  • fileName - the file name with its extension, up to 255 characters.
  • fileSize - the exact file size in bytes.

Response 201:

{
  "uploadId": "6a1f2763e4b82c58360f9704",
  "uploadUrl": "https://...",
  "method": "PUT",
  "headers": { "Content-Length": "48234112" },
  "expiresAt": "2026-10-12T10:15:00.000Z"
}

Errors: 400 API-FILE-02, 400 API-UPLOAD-03, 404 WF-NF-01, 413 FILE-UP-SIZE-01 - as above.

2. Upload the bytes

Send the file with an HTTP PUT to uploadUrl, with the returned headers, before expiresAt (15 minutes). Do not send the Authorization header to this URL.

3. Finish the upload

POST /workflows/{workflowId}/documents/uploads/{uploadId}/complete

No body. Starts processing the document.

Response 202: the new document, as in Send a document.

Errors:

  • 400 API-UPLOAD-02 - the file was not uploaded, or its size does not match fileSize.
  • 404 API-UPLOAD-01 - the upload does not exist or has expired. Request a new upload URL.

Documents

The document object

{
  "id": "6a1f2763e4b82c58360f9703",
  "name": "invoice-1042.pdf",
  "status": "approved",
  "workflowId": "6a1f2763e4b82c58360f9702",
  "workflowName": "Invoices",
  "pageCount": 2,
  "confidenceScore": 0.94,
  "createdAt": "2026-10-12T10:00:00.000Z",
  "updatedAt": "2026-10-12T10:00:30.000Z",
  "fields": {
    "fields": [
      {
        "docType": "invoice",
        "fields": [
          {
            "attribute": "InvoiceId",
            "text": "INV-1042",
            "type": "string",
            "confidence": 0.98,
            "fields": []
          },
          {
            "attribute": "Items",
            "text": "",
            "type": "array",
            "fields": [
              { "attribute": "Description", "text": "Packing boxes", "row": 1, "fields": [] },
              { "attribute": "Amount", "text": "250.00", "row": 1, "fields": [] }
            ]
          }
        ]
      }
    ]
  }
}
  • status - pending, running, paused, processed, awaiting_approval, review, rejected, approved, exported, or failed. See File statuses.
  • confidenceScore - overall confidence from 0 to 1.
  • fields - the extracted results, present once processing has finished. One entry per document type found, each with its fields:
    • attribute - the field name, as listed by the fields endpoint.
    • text - the value as it appears in the document.
    • value - a normalized value where available, for example a date as 2022-10-21 or an amount as { "amount": 17, "currencyCode": "EUR" }.
    • confidence - the field's confidence from 0 to 1.
    • fields - sub-fields. Line-item columns carry a row number; values with the same row belong to one line.
    • Fields can also carry the position of the value on the page (zone, words).

List documents

GET /documents

Documents of the workflows connected to this integration, newest first.

Query parameters:

  • workflowId (optional) - only documents of this workflow.
  • status (optional) - completed, needs_review, failed, or processing.
  • limit (optional) - 1 to 50, default 10.

Response 200: an array of document objects.

Errors:

  • 400 - an invalid workflowId, status, or limit.

Get a document

GET /documents/{documentId}

Response 200: a document object, with fields once processing has finished.

Errors:

  • 404 FILE-NF-01 - the document does not exist or is not in a connected workflow.

Download the results as a file

GET /documents/{documentId}/results?format=csv

The extracted results of a finished document as a file download.

Query parameters:

  • format (required) - json, csv, or xlsx (Excel - Growth and Scale plans).

Response 200: the file, with Content-Type application/json, text/csv, or application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, and a Content-Disposition file name such as invoice-1042-results.csv.

Errors:

  • 400 - format is missing or not one of the three.
  • 403 API-RESULTS-02 - the format is not included in the account's plan.
  • 404 FILE-NF-01 - the document does not exist or is not in a connected workflow.
  • 409 API-RESULTS-01 - the results are not ready yet. Wait until the document has finished processing and, if the workflow requires it, has been approved.

GET /documents/{documentId}/original

Response 200:

{
  "url": "https://...",
  "expiresAt": "2026-10-12T11:00:00.000Z"
}

url downloads the original uploaded file and works for one hour. Do not send the Authorization header to it.

Errors:

  • 404 FILE-NF-01 - the document does not exist or is not in a connected workflow.

Event subscriptions

Subscribe a URL to receive document events as they happen. The event payload, signature headers, and delivery rules are described in Zapier and n8n - Events.

Subscribe

POST /webhooks

Body:

{
  "targetUrl": "https://hooks.example.com/foxello",
  "event": "document.completed",
  "workflowId": "6a1f2763e4b82c58360f9702"
}
  • targetUrl - a public https address on the standard port (443).
  • event - document.completed, document.needs_review, document.approved, or document.failed.
  • workflowId (optional) - only events of this workflow. Leave it out to receive events of every workflow that sends results to this integration.

Response 201:

{
  "id": "6a1f2763e4b82c58360f9705",
  "event": "document.completed",
  "workflowId": "6a1f2763e4b82c58360f9702",
  "status": "active",
  "createdAt": "2026-10-12T10:00:00.000Z",
  "secret": "whsec_..."
}

secret signs every delivery of this subscription. It is returned only here - store it.

Errors:

  • 400 WEBHOOK-02 - the URL is not allowed.
  • 400 WEBHOOK-03 - the account already has 200 active subscriptions.
  • 400 - the workflow does not send results to this integration, or the body is invalid.

Get a subscription

GET /webhooks/{subscriptionId}

Response 200:

{
  "id": "6a1f2763e4b82c58360f9705",
  "event": "document.completed",
  "workflowId": "6a1f2763e4b82c58360f9702",
  "status": "active",
  "createdAt": "2026-10-12T10:00:00.000Z"
}

status is active, or disabled after repeated failed deliveries.

Errors:

  • 404 WEBHOOK-01 - the subscription does not exist.

Unsubscribe

DELETE /webhooks/{subscriptionId}

Response 200:

{ "deleted": true }

Errors:

  • 404 WEBHOOK-01 - the subscription does not exist.

A receiver can also unsubscribe by answering a delivery with 410 Gone.

Need more help?

Signed-in users can reach our team from Support in the app, or contact us.

Ready to try it on your own documents?

Create a workflow, upload a document, and see structured results in minutes.

Start free - no card