n8n Outbound Delivery
Recommended n8n integration pattern for reviewed Numora documents, delivery outbox polling, dispatch, and optional delivery callbacks.
Scope
This page describes the recommended public API pattern for connecting reviewed Numora documents to downstream systems with n8n.
The current provider shown in examples is dynamics365.
Recommended Modes
Numora supports two outbound delivery modes.
1. Numora-Managed Downstream Execution
This is the recommended model for multi-tenant SaaS integrations.
- End users configure the downstream connection and workflow inside Numora.
n8npolls the delivery outbox and callsdispatch.- Numora reuses the saved connection and internal workflow to perform the downstream write.
n8ndoes not need to store per-user Dataverse credentials.
Recommended flow:
GET /v1/delivery/outboxPOST /v1/documents/{id}/dispatch- Poll
GET /v1/documents/{id}until the document leavespush_pending
In this mode, POST /v1/documents/{id}/delivery is not required.
2. External Executor With Delivery Callback
Use this mode only when the downstream write is performed outside Numora.
n8nor another worker fetches the document result.- The external worker writes to the destination system directly.
- The external worker calls the delivery callback to record success or failure.
- If you still want end users to manage Dynamics connections inside Numora,
n8ncan request a short-lived Dataverse token from Numora instead of storing the client secret itself.
Recommended flow:
GET /v1/delivery/outboxGET /v1/documents/{id}/resultPOST /v1/dynamics/session- Write to the destination system
POST /v1/documents/{id}/delivery
In this mode, do not call POST /v1/documents/{id}/dispatch. dispatch still routes into Numora's internal workflow engine and does not replace the old workflow logic.
Poll the Delivery Outbox
GET /v1/delivery/outbox?provider=dynamics365&limit=100
Example request:
curl "https://api.numora.example/v1/delivery/outbox?provider=dynamics365&limit=100" \
-H "Authorization: Bearer $NUMORA_API_KEY" \
-H "x-request-id: n8n-outbox-001"Example response:
{
"data": [
{
"document_id": "4be38121-3791-4856-80d5-c57dbec2cf78",
"schema": "invoice_v2",
"status": "reviewed",
"external_id": null,
"metadata": {},
"result_url": "/v1/documents/4be38121-3791-4856-80d5-c57dbec2cf78/result",
"dispatch_url": "/v1/documents/4be38121-3791-4856-80d5-c57dbec2cf78/dispatch",
"updated_at": "2026-03-24T02:36:37.684Z"
}
],
"meta": {
"provider": "dynamics365",
"next_cursor": null
}
}Notes:
- The outbox returns reviewed and finalized documents that are eligible for downstream delivery.
- Documents already in
push_pendingorpush_succeededare excluded. next_cursoris opaque and should be passed back unchanged when paginating.
Dispatch a Reviewed Document
POST /v1/documents/{id}/dispatch
Example request:
curl -X POST "https://api.numora.example/v1/documents/4be38121-3791-4856-80d5-c57dbec2cf78/dispatch" \
-H "Authorization: Bearer $NUMORA_API_KEY" \
-H "Content-Type: application/json" \
-H "x-request-id: n8n-dispatch-001" \
-d '{
"provider": "dynamics365"
}'Example response:
{
"data": {
"id": "4be38121-3791-4856-80d5-c57dbec2cf78",
"schema": "invoice_v2",
"status": "push_pending",
"external_id": null,
"metadata": {},
"review_state": {
"version": 1,
"confirmed_general_field_names": ["invoice_number"],
"confirmed_line_item_ids": []
},
"duplicate_of": null,
"created_at": "2026-03-20T20:25:04.644Z",
"updated_at": "2026-03-24T02:36:37.684Z",
"status_url": "/v1/documents/4be38121-3791-4856-80d5-c57dbec2cf78",
"result_url": "/v1/documents/4be38121-3791-4856-80d5-c57dbec2cf78/result",
"dispatch_url": "/v1/documents/4be38121-3791-4856-80d5-c57dbec2cf78/dispatch"
},
"meta": {
"run_id": "18e1224c-fb6c-429e-89a3-9d3ee96ff7a9"
}
}Notes:
dispatchis asynchronous. Treat202 Acceptedas “queued,” not “completed.”- If the document is not both reviewed and finalized, the API returns
409 conflict. - If no active downstream workflow is available, the API returns
409 conflict.
Poll Document Status After Dispatch
GET /v1/documents/{id}
Recommended status handling:
push_pending: downstream execution is still queued or runningpush_succeeded: downstream execution completed successfullypush_failed: the latest downstream attempt failed and may require retry or operator action
For dispatch mode, this status resource is the primary completion signal for n8n.
Record an External Delivery Result
POST /v1/documents/{id}/delivery
Use this only when the downstream write is executed outside Numora.
Success example:
curl -X POST "https://api.numora.example/v1/documents/4be38121-3791-4856-80d5-c57dbec2cf78/delivery" \
-H "Authorization: Bearer $NUMORA_API_KEY" \
-H "Content-Type: application/json" \
-H "x-request-id: n8n-delivery-success-001" \
-d '{
"provider": "dynamics365",
"status": "succeeded",
"external_record_id": "crm-row-001",
"execution_id": "n8n-4be38121-3791-4856-80d5-c57dbec2cf78",
"attempted_at": "2026-03-24T03:00:00.000Z"
}'Failure example:
curl -X POST "https://api.numora.example/v1/documents/4be38121-3791-4856-80d5-c57dbec2cf78/delivery" \
-H "Authorization: Bearer $NUMORA_API_KEY" \
-H "Content-Type: application/json" \
-H "x-request-id: n8n-delivery-failed-001" \
-d '{
"provider": "dynamics365",
"status": "failed",
"execution_id": "n8n-4be38121-3791-4856-80d5-c57dbec2cf78",
"error_code": "crm_429",
"error_message": "Dataverse rate limited",
"attempted_at": "2026-03-24T03:00:00.000Z"
}'The callback is idempotent by execution_id.
- Replaying the same
execution_idwith the same payload is accepted. - Replaying the same
execution_idwith different delivery data returns409 conflict.
Request a Short-Lived Dataverse Session
POST /v1/dynamics/session
Use this only for the external executor mode, where n8n replaces the old workflow logic but still relies on a Dynamics connection that the end user configured inside Numora.
Example request:
curl -X POST "https://api.numora.example/v1/dynamics/session" \
-H "Authorization: Bearer $NUMORA_API_KEY" \
-H "Content-Type: application/json" \
-H "x-request-id: n8n-dynamics-session-001" \
-d '{}'Example response:
{
"data": {
"provider": "dynamics365",
"token_type": "Bearer",
"access_token": "<short-lived-dataverse-token>",
"organization_url": "https://org.crm.dynamics.com",
"organization_origin": "https://org.crm.dynamics.com",
"api_base_url": "https://org.crm.dynamics.com/api/data/v9.2",
"connection": {
"id": "conn_123",
"status": "active",
"organization_url": "https://org.crm.dynamics.com",
"tenant_id": "tenant-id",
"client_id": "client-id"
}
}
}Notes:
- The stored client secret is never returned.
- The bearer token is intended for trusted workers such as your own
n8n. - If you need a specific Dynamics connection, send
connection_idin the JSON body. - If the executor intentionally finishes without creating CRM rows, for example because a supplier lookup misses, send
status=skippedtoPOST /v1/documents/{id}/delivery. Numora will treat that as a completed no-write outcome and keep the document out of automatic outbox retries.
Invoice_v2 Executor Mapping
If you are replacing the current invoice workflow with n8n, use this shape:
- Poll
GET /v1/delivery/outbox. - Split each returned item.
- Fetch
GET /v1/documents/{id}/result. - Read fields from
data.data.fieldsand line items fromdata.data.line_items. - Request
POST /v1/dynamics/session. - Query Dataverse
teamby the fixed owner name. - Query Dataverse
otcm_supplierbyvendor_name. - If the supplier lookup misses, callback
status=skipped. - If the supplier lookup succeeds, create
otcm_inboundinvoice. - Loop through
line_itemsand createotcm_inboundinvoicelineitem. - Callback
status=succeededwith the created invoice record id.
Useful field paths:
fields.invoice_number.valuefields.invoice_date.valuefields.due_date.valuefields.vendor_name.valuefields.subtotal.valuefields.tax_amount.valuefields.invoice_total.valueline_items[*].descriptionline_items[*].quantityline_items[*].unit_priceline_items[*].amountline_items[*].tax_code
Retrieve Delivery Attempts
GET /v1/documents/{id}/delivery?provider=dynamics365&limit=20
Use this resource to inspect recorded delivery attempts from callback-based integrations.
Suggested n8n Polling Strategy
For the recommended Numora-managed dispatch mode:
- Schedule polling every 5 to 10 minutes.
- Call
GET /v1/delivery/outbox. - Split returned items.
- Call each item's
dispatch_url. - Store
document_idandmeta.run_idfor observability. - Poll
GET /v1/documents/{id}or inspect workflow runs until the status leavespush_pending.
This model keeps destination credentials and workflow configuration inside Numora.
Related Pages
Idempotency and External Identifiers
Current idempotency model for document creation and delivery callbacks in the Numora Public API developer preview.
Schemas, Destinations, and Mappings
Destination model, schema catalog, mapping resources, and downstream write-back rules for the Numora Public API developer preview.