# Integration

An Integration connects a platform to an external system. Its type decides how: `manual` (a built-in connector such as Transics or Webfleet, with credentials and enabled functions), `configured` (user-built data sources with field mappings, started by entity events, a schedule or incoming calls), `fileTemplate` (maps documents with a known layout onto entities), `messageAutomation`, or `apiAccess` (a key pair for calling this API). Every unit of work is stored as an integration object, handled by tasks that write logs and redacted HTTP request logs; these can be listed with shared filters and traced as one run. Incoming data arrives through public webhook URLs (per connector listener or per web-hook data source, authenticated by the data source's credentials or an IP allow-list) and through inbound email. Integrations can be tested with saved test cases, drafted with AI, and are soft-deleted.

## Update an integration test

 - [PUT /integration/{id}/test/{testId}](https://docs.transportial.com/apis/integration/update:integration:test.md): Replaces the definition of a saved test case. Blank name, description, input and expectedOutput keep their stored values, and an absent or unknown dataSourceId keeps the stored data source. assertions, validationMode, the notification toggles and the recipient lists are taken as sent, so an empty list clears them and null toggles fall back to the platform defaults. The last run result is kept.

Permission: update:integration

Errors: 400 when the body cannot be parsed; 404 when no test with this id exists on your platform.

## Delete an integration test

 - [DELETE /integration/{id}/test/{testId}](https://docs.transportial.com/apis/integration/delete:integration:test.md): Permanently removes a saved test case.

Permission: delete:integration

Errors: 404 when no test with this id exists on your platform.

## List integrations

 - [GET /integrations/{offset}/{amount}](https://docs.transportial.com/apis/integration/get:integrations.md): Returns one page of the integrations of your platform. Deleted and archived integrations are not included.

Each item is serialised as its concrete integration type (manual, configured, fileTemplate, messageAutomation or apiAccess), selected by the type property.

Pagination: offset and amount are path segments. totalResults holds the total number of integrations, independent of the page.

Permission: get:integrations

Errors: 400 when offset is not a number.

## Search integrations

 - [POST /integrations/{offset}/{amount}](https://docs.transportial.com/apis/integration/search:integrations.md): Full-text search over the integrations of your platform. Deleted and archived integrations are never returned.

All body properties are optional and combined with AND:
- query matches the integration's search text (name, description and similar) as a phrase with a slop of 10;
- types restricts to integration types (manual, configured, fileTemplate, messageAutomation, apiAccess);
- manualType / manualTypes restrict manual integrations to one or more connectors (for example transics);
- sectorType restricts to one sector (for example boardComputer).

An empty body ({}) returns every integration. If the search index fails, an empty page is returned instead of an error.

Pagination: offset and amount are path segments; amount is passed to the search index as is (not clamped). totalResults holds the total number of hits.

Permission: get:integrations

Errors: 400 when the body is not valid JSON or offset/amount is not a number.

## Receive a webhook for a connector listener

 - [GET /integration/{id}/{token}](https://docs.transportial.com/apis/integration/handle:integration:webhook.md): Public endpoint an external system calls to push data to a manual (connector) integration. Accepts POST, PUT, GET and DELETE.

{token} is the name of the connector listener to run (for example ReceiveX12 for X12, ReceiveUpdates for WhatsApp), matched case-insensitively against the listeners of the integration's connector.

Authentication: none on the Transportial side beyond knowing the integration id and listener name. Provider-specific verification (signatures, verify tokens) is done by the listener itself where the provider offers it. A listener that requires a shared secret (Shippeo: its configured inbound header and secret) is checked before anything is stored; a failed check answers 401.

Behaviour:
1. The raw body is always stored as an integration object first, so nothing is lost.
2. If the integration is disabled, the object is marked ERROR and 405 is returned.
3. Otherwise a webhook task is created. If every matching listener is asynchronous, the object is queued for the listener job and 201 "Queued for processing" is returned immediately. Otherwise the listeners run inline; a listener may write its own response (for example a provider handshake), else 201 "Successfully handled" is returned.
4. If handling throws, the object is scheduled for retry, the error is logged on the integration and 500 is returned.

Permission: Public, no authentication.

Errors: 401 when the listener refuses the call; 404 when the integration does not exist; 405 when it is disabled; 500 when handling failed.

## Run an integration test

 - [POST /integration/{id}/test/{testId}/run](https://docs.transportial.com/apis/integration/run:integration:test.md): Runs one saved test case: its input is fed through the test's data source mapping (nothing is created) and the output is judged on the expected output and/or assertions, as set by validationMode. The test's lastStatus, lastResultMessage and lastRunAt are updated, and failure notifications are sent according to the test and platform settings.

A test without a data source, or whose mapping throws, is reported as failed rather than as an error.

Permission: get:integration

Errors: 404 when no test with this id exists on your platform.

## Set the OpenID token of an integration

 - [PUT /integration/{id}/openId](https://docs.transportial.com/apis/integration/update:integration:openidtoken.md): Completes the OpenID authorisation flow of a manual integration: stores the token returned by the provider on the integration's credentials and lets the connector exchange it (for example for access and refresh tokens), after which the integration can authenticate.

The token is read from the JSON body property token. The integration is looked up within the platform of the calling session.

Permission: update:integration

Errors: 403 without a session; 401 without the permission; 404 when no integration with this id exists on the caller's platform. A response with success = false and code = 400 (HTTP status 200) when the integration is not a manual integration, or its authentication method is not openId or clientKeysOpenId.

## Preview a cron schedule

 - [POST /integration/schedule/preview](https://docs.transportial.com/apis/integration/preview:integration:schedule.md): Checks a cron expression and returns the next moments it would fire, without saving anything. Use it to show what an expression means before it is stored on an integration schedule.

Dialect: 5 fields (minute hour day-of-month month day-of-week) are read as Unix cron, so 0 6   1-5 is Monday to Friday 06:00; 6 or 7 fields are read as Quartz cron (with seconds and optional year, supporting L, W and #). The macros @hourly, @daily, @midnight, @weekly, @monthly, @yearly and @annually are expanded.

The runs are computed in cronTimezone; a blank or unknown zone falls back to UTC, and timezone in the response says which zone was used. count is clamped to 1..20. An invalid expression returns valid = false and no runs, not an error.

Permission: get:integrations

Errors: 400 when the body is not valid JSON.

## Test a data source mapping

 - [POST /integration/dataSource/mapping:test](https://docs.transportial.com/apis/integration/test:integration:datasourcemapping.md): Runs a sample payload through an unsaved data source configuration and returns the result, without creating or changing anything.

The payload is parsed (JSON, XML, CSV, X12, EDIFACT or base64 file) and checked against the data source's filters. When it passes, an OTM data source returns the payload serialised as OTM entities; any other data source returns the JSON produced by its field mapping. When the filters reject the payload the result is empty.

Permission: create:integration

Errors: 400 when the body cannot be parsed.

## Generate integration credentials

 - [POST /integration/generate/credentials](https://docs.transportial.com/apis/integration/generate:integration:credentials.md): Generates fresh secrets for the authentication method in the body and returns the credentials; nothing is stored. Use it to issue credentials that an external system must send when it calls one of your incoming webhook data sources.

Per authenticationMethod:
- basic: a new UUID username and a 40-character password;
- apiKey: a 100-character apiKey;
- bearer: a signed JWT bearer token (a 100-character random value if signing fails);
- accessKeys: a UUID accessKey and a 100-character secretKey.

Other methods are returned unchanged. All other properties of the body are echoed back.

Permission: generate:integration:credentials

Errors: 400 when the body cannot be parsed.

## Update an integration

 - [PUT /integration](https://docs.transportial.com/apis/integration/update:integration.md): Updates an existing integration. The body must carry the integration's id; the stored integration is merged with the properties sent.

Side effects: every task of this integration that is still queued or processing is marked as ERROR, so work started under the old configuration does not continue. The same save-time rules as on create apply (cron validation, webhook token generation, connector setup, fingerprints).

Permission: update:integration

Errors: 400 when the body cannot be parsed or the cron expression is invalid; 400 with message integration_manual_type_unavailable when the update would create an integration on, or switch one to, a connector that is not offered for new integrations; 404 when no integration with the given id exists on your platform.

## Create an integration

 - [POST /integration](https://docs.transportial.com/apis/integration/create:integration.md): Creates an integration on your platform. The type property selects the concrete kind (manual, configured, fileTemplate, messageAutomation, apiAccess) and therefore which other properties apply.

Side effects on save:
- a schedule's interval is converted to milliseconds; a cron schedule that does not parse is rejected;
- every incoming web-hook data source without a token gets a random 15-character token, which forms its webhook URL;
- manual integrations get their sectorType from the connector and run the connector's own setup;
- configured integrations copy the first of triggerEvents into the legacy triggerEvent;
- file-template integrations get their matrix and HTML fingerprints computed.

Permission: create:integration

Errors: 400 when the body cannot be parsed (unknown type, wrong value types) or the schedule's cron expression is invalid; 400 with message integration_manual_type_unavailable when manualType is a connector that is not offered for new integrations (available: false in the platform's integrationManualTypes).

## Upload a file for a file template

 - [POST /integration/file/upload](https://docs.transportial.com/apis/integration/integration:fileupload.md): Uploads an example document for a file-template integration. The file is stored on your platform and converted to a cell matrix and an HTML rendering, which the template editor uses to place fields; the matching fingerprints are returned so the template can later recognise documents with the same layout.

Send multipart/form-data with the file in the part named file. PDF, Word and Excel (or other spreadsheet) content types are accepted.

Permission: integration:fileUpload

Errors: a response with success = false and code = 400 (HTTP status 200) when the file part is missing or its content type is not supported.

## Get virtual FTP connection details

 - [GET /integration/virtualFtp/details](https://docs.transportial.com/apis/integration/get:integration:virtualftpdetails.md): Returns the host and port of the platform-hosted (virtual) FTP server that virtual FTP data sources connect through. The values come from the running server's configuration, so they are correct for the current environment, unlike values stored on older data sources.

Permission: get:integration

## Test a file template mapping

 - [POST /integration/fileTemplate/mapping:test](https://docs.transportial.com/apis/integration/test:integration:filetemplatemapping.md): Applies an unsaved file-template integration to its own matrix (spreadsheet cells) and html (document rendering) and returns the JSON its fields produce, without saving anything.

When the first field is of type ARRAY the result is a JSON array (only object rows are kept); otherwise it is a JSON object.

Permission: create:integration

Errors: 400 when the body cannot be parsed.

## List tests of an integration

 - [GET /integration/{id}/test](https://docs.transportial.com/apis/integration/get:integration:tests.md): Returns the saved test cases of an integration: sample input, expected output and/or assertions, notification settings and the result of the last run.

At most the first 50 tests are returned; totalResults holds the total number of tests.

Permission: get:integration

Errors: 404 when no integration with this id exists on your platform.

## Create an integration test

 - [POST /integration/{id}/test](https://docs.transportial.com/apis/integration/create:integration:test.md): Saves a new test case for an integration: an input payload to run through one of its data sources, and the expected output and/or assertions the result is judged on. The test is not run on creation (lastStatus is NOT_RUN).

A dataSourceId that does not resolve is stored as no data source; running such a test fails with "No data source configured for this test".

Permission: create:integration

Errors: 400 when the body cannot be parsed; 404 when no integration with this id exists on your platform.

## Import data through a field mapping

 - [POST /integration/import/data](https://docs.transportial.com/apis/integration/import:integration:data.md): Maps a raw data payload onto platform entities with the given field mapping and creates those entities (or updates the existing entity the mapped data resolves to) on your platform. This is the backend of the import tool: upload a file, map its columns, import.

data may be JSON, XML, CSV, X12, EDIFACT, or a base64-encoded file (including Excel workbooks); the format is detected automatically. When the first mapping field is of type ARRAY the result is a list and one entity is created per mapped row; otherwise a single entity is created. Array fields addressed with an empty [] selector are appended to the entity the row resolves to instead of replacing its collection, so one row per child (for example one vehicle per row of a fleet) accumulates.

The created entities trigger their usual save side effects (live updates, message automations, integrations).

Permission: integration:import-data

Errors: 400 when the body cannot be parsed or entityType is unknown.

## Get an integration

 - [GET /integration/{id}](https://docs.transportial.com/apis/integration/get:integration.md): Returns one integration of your platform, serialised as its concrete type (selected by type), including its data sources, schedule and notes.

Permission: get:integration

Errors: 404 when no integration with this id exists on your platform, or it is deleted or archived.

## Delete an integration

 - [DELETE /integration/{id}](https://docs.transportial.com/apis/integration/delete:integration.md): Soft-deletes an integration: it is flagged as deleted, disappears from lists and lookups, and is no longer scheduled or triggered. Its logs, tasks and objects are kept.

Permission: delete:integration

Errors: 404 when no integration with this id exists on your platform, or it is already deleted or archived.

## Receive a webhook for an incoming data source

 - [GET /integration/{id}/dataSource/{dataSourceId}/{token}](https://docs.transportial.com/apis/integration/handle:integration:datasourcewebhook.md): Public endpoint an external system calls to push data into one incoming web-hook data source of an integration. Accepts POST, PUT, GET and DELETE. The full URL (/integration/{id}/dataSource/{dataSourceId}/{token}) is shown on the data source; token is generated when the data source is saved.

Authentication (decided by the data source; any mismatch, including a wrong dataSourceId/token pair, gives 401):
- hasAuthentication = true: the request must carry the data source's credentials, by authenticationMethod:
  - apiKey: header X-API-KEY equal to the credentials' apiKey;
  - accessKeys: headers X-API-KEY (access key) and X-API-SECRET (secret key);
  - bearer: Authorization: Bearer  (or an Authorization cookie) holding an unexpired JWT signed by Transportial;
  - basic: HTTP Basic authentication with the credentials' username and password;
  - any other method is always rejected.
- hasAuthentication = false: the caller's IP address must be in the data source's allowedIps.

Behaviour:
1. The raw body is always stored as an integration object first.
2. If the integration is disabled the object is marked ERROR and 405 is returned.
3. Otherwise a webhook task is created, authentication is checked and the payload is matched against the data source's filters (405 when it does not pass). A passing payload is mapped with the data source's field mapping and the resulting entities are created or updated; 201 is returned. Data sources with sequentialProcessing handle one call at a time.
4. If handling throws, the object is scheduled for retry, the error is logged and 500 is returned.

Permission: Public, no authentication (the data source's own authentication applies).

Errors: 401 when authentication fails or the data source/token pair is unknown; 404 when the integration does not exist; 405 when the integration is disabled or the filters reject the payload; 500 when handling failed.

## List the functions of a connector

 - [GET /integration/type/{type}/functions](https://docs.transportial.com/apis/integration/get:integration:functions.md): Returns the names of all functions (handlers) a manual connector offers, for example the scheduled syncs and event handlers of Transics, plus a description per function where one is available. The names are the values a manual integration's enabledFunctions accepts.

An unknown connector type returns an empty list rather than an error.

Permission: get:integrationFunctions

## Generate an integration with AI

 - [POST /integration/generate](https://docs.transportial.com/apis/integration/generate:integration.md): Uses your platform's configured AI model to draft an integration configuration from a free-text description and/or uploaded documents (for example API documentation). Nothing is saved: the draft is returned as integration JSON that the client can review and then send to POST /integration.

documents are file ids on your platform; ids that do not resolve to a file are ignored.

Permission: create:integration

Errors: 400 when the body cannot be parsed.

## Run all tests of an integration

 - [POST /integration/{id}/test/run](https://docs.transportial.com/apis/integration/run:integration:tests.md): Runs every saved test case of an integration, one after another, and returns each result plus pass/fail totals. Each test's last status is stored and failure notifications are sent as for a single run.

Permission: get:integration

Errors: 404 when no integration with this id exists on your platform.

## List HTTP request logs of an integration

 - [GET /integration/{id}/requestLogs/{offset}/{amount}](https://docs.transportial.com/apis/integration/get:integration:requestlogs.md): Returns one page of the outbound HTTP requests an integration made, newest first, with URL, request and response body and response code. Credentials are redacted before request logs are stored.

relations maps every returned request log id to its task (id and name), the task's integration object and sibling counts.

Filtering: all query parameters are optional and combined with AND; without any, the unfiltered list is returned. The same filter contract applies to the objects, tasks, logs and request-logs lists, so a filter can be kept while switching between them.

Pagination: offset and amount are path segments; totalResults holds the total number of matching rows.

Permission: get:integrationRequestLogs

Errors: 404 when no integration with this id exists on your platform.

## Receive an inbound email

 - [POST /integration/email](https://docs.transportial.com/apis/integration/handle:integration:email.md): Public endpoint called by SendGrid Inbound Parse for every email sent to an integration's inbound address (@...transportial.com). The email's form fields are stored as an integration object and handed to that data source.

Authentication:
- the recipient address selects the data source (by id) and thereby the integration and platform;
- when the platform has allowed email domains configured, the sender's domain must be one of them (400 otherwise);
- a data source with hasAuthentication = false only accepts calls from an IP address in its allowedIps (401 otherwise). SendGrid posts every inbound email to this one URL and cannot present per-data-source credentials, so for hasAuthentication = true the inbound address and the allowed sender domains are the gate.

Behaviour: when the integration is enabled and the email passes the data source's filters, it is mapped and handled like any incoming data source payload and 201 is returned; otherwise the object is marked ERROR and 405 is returned.

Permission: Public, no authentication (see above).

Errors: 400 when the form has no envelope or no recipient on a transportial.com domain, when the data source cannot be resolved ("Platform not found") or the sender's domain is not allowed; 401 when the caller's IP is not allowed; 405 when the integration is disabled or missing, or the filters reject the email.

## Generate a data source mapping with AI

 - [POST /integration/dataSource/mapping:generate](https://docs.transportial.com/apis/integration/generate:integrationdatasourcemapping.md): Uses your platform's configured AI model to generate the field mappings of one data source. The model receives the field structure of the target entity type, the direction and data type, and the optional description, sample data and documents. Nothing is saved: the returned fields can be assigned to the data source's fields directly.

documents are file ids on your platform; ids that do not resolve to a file are ignored.

Permission: create:integration

Errors: 400 when the body cannot be parsed or entityType is unknown.

## List tasks of an integration

 - [GET /integration/{id}/tasks/{offset}/{amount}](https://docs.transportial.com/apis/integration/get:integration:tasks.md): Returns one page of the integration tasks of an integration, newest first. A task is one run of a handler: a scheduled sync, a webhook call or the handling of one integration object.

relations maps every returned task id to its related counts and its integration object.

Filtering: all query parameters are optional and combined with AND; without any, the unfiltered list is returned. The same filter contract applies to the objects, tasks, logs and request-logs lists, so a filter can be kept while switching between them.

Pagination: offset and amount are path segments; totalResults holds the total number of matching rows.

Permission: get:integrationTasks

Errors: 404 when no integration with this id exists on your platform.

## List logs of an integration

 - [GET /integration/{id}/logs/{offset}/{amount}](https://docs.transportial.com/apis/integration/get:integration:logs.md): Returns one page of the log lines written by an integration, most recently updated first. Each log has a level (info, warning, success, error), a message and usually the task that wrote it.

relations maps every returned log id to its task (id and name), the task's integration object and sibling counts.

Filtering: all query parameters are optional and combined with AND; without any, the unfiltered list is returned. The same filter contract applies to the objects, tasks, logs and request-logs lists, so a filter can be kept while switching between them.

Pagination: offset and amount are path segments; totalResults holds the total number of matching rows.

Permission: get:integrationLogs

Errors: 404 when no integration with this id exists on your platform.

## Trace an integration activity row

 - [GET /integration/{id}/trace/{type}/{traceId}](https://docs.transportial.com/apis/integration/get:integration:trace.md): Reassembles the whole run around one activity row: the integration object that started it (if any), and every task of that run ordered oldest first, each with its own logs and request logs and its parent task for nesting.

A trace is capped at 200 tasks, 1000 logs and 1000 request logs; truncated is true when a cap was hit, and the paginated lists should be used for the rest.

Permission: get:integrationLogs

Errors: 400 when type is not one of object, task, log, requestLog; 404 when no integration with this id exists on your platform, or no row of the given type and id belongs to it.

## List objects queued for an integration

 - [GET /integration/{id}/objects/{offset}/{amount}](https://docs.transportial.com/apis/integration/get:integration:objects.md): Returns one page of the integration objects of an integration, newest first. An integration object is one queued unit of work: an entity change or an incoming payload (webhook, email, file) waiting for, being, or done being handled.

relations maps every returned object id to its related counts (tasks, logs and request logs produced while handling it).

The value search column contains the raw payload, so q can find the object that carried a given reference.

Filtering: all query parameters are optional and combined with AND; without any, the unfiltered list is returned. The same filter contract applies to the objects, tasks, logs and request-logs lists, so a filter can be kept while switching between them.

Pagination: offset and amount are path segments; totalResults holds the total number of matching rows.

Permission: get:integrationObjects

Errors: 404 when no integration with this id exists on your platform.

