Preview a sample settlement/report file against a provider mapping
Parses a sample file (multipart upload) and returns the detected or auto-suggested provider column mapping plus the first parsed rows, so an operator can review a mapping before saving it. Nothing is persisted: the sample is written to a temp workspace that is removed before the response returns. Resolution order: a `profile` part (an UNSAVED draft profile) wins; otherwise `provider_id` names a stored provider; otherwise the file is matched against the tenant's active providers; otherwise — for CSV samples with no match — a best-effort mapping is derived from the file's own header row. `profile` and `provider_id` are mutually exclusive. The `profile` part exists so an operator can prove a fix BEFORE saving it, which is what makes the mandatory-preview-before-activation guard non-circular. A draft is validated with the same save-time gate `POST /integrations` applies, so an invalid draft returns per-key field errors rather than an opaque parse failure. A draft whose detection rules do not match the sample is rejected 422 `no_detection_rule_matched` with the per-rule `detection_trace`, never a misleading empty success. Output is capped at 20 parsed rows.
Parses a sample file (multipart upload) and returns the detected or auto-suggested provider column mapping plus the first parsed rows, so an operator can review a mapping before saving it. Nothing is persisted: the sample is written to a temp workspace that is removed before the response returns.
Resolution order: a profile part (an UNSAVED draft profile) wins; otherwise provider_id names a stored provider; otherwise the file is matched against the tenant's active providers; otherwise — for CSV samples with no match — a best-effort mapping is derived from the file's own header row. profile and provider_id are mutually exclusive.
The profile part exists so an operator can prove a fix BEFORE saving it, which is what makes the mandatory-preview-before-activation guard non-circular. A draft is validated with the same save-time gate POST /integrations applies, so an invalid draft returns per-key field errors rather than an opaque parse failure. A draft whose detection rules do not match the sample is rejected 422 no_detection_rule_matched with the per-rule detection_trace, never a misleading empty success. Output is capped at 20 parsed rows.
Authorization
bearerAuth In: header
Request Body
multipart/form-data
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/api/recon/v1/integrations/preview" \ -F file="string"{
"detected_provider": "bri_statement",
"suggested_mapping": [
{
"source_column": "MUTASI_DEBET",
"source_index": 8,
"canonical_field": "debit_amount",
"confidence": 0.95
}
],
"rows": [],
"row_count": 0,
"truncated": false,
"detection_trace": [
{
"rule": "filename_pattern",
"expected": "^BRI_.*\\.csv$",
"scope": "file_name",
"tested_against": "BRI_20260730.csv",
"matched": true
}
],
"skipped": [],
"skipped_count": 0
}{
"error": "validation_failed",
"message": "Request body is invalid",
"request_id": "01900000-0000-7000-8000-000000000001"
}{
"error": "unauthorized",
"message": "Bearer token is missing or invalid",
"request_id": "01900000-0000-7000-8000-000000000001"
}{
"error": "not_found",
"message": "The requested resource was not found",
"request_id": "01900000-0000-7000-8000-000000000001"
}{
"error": "file_too_large",
"message": "file exceeds the 10 MiB preview limit",
"request_id": "0190b5c2-1a2b-7c3d-8e4f-5a6b7c8d9e0f"
}{
"error": "no_detection_rule_matched",
"message": "no detection rule matched this sample; see detection_trace for what was evaluated",
"request_id": "0190b5c2-1a2b-7c3d-8e4f-5a6b7c8d9e0f",
"detection_trace": [
{
"rule": "filename_pattern",
"expected": "^BRI_\\d+\\.csv$",
"scope": "file_name",
"tested_against": "statement.csv",
"matched": false
},
{
"rule": "content_sniff",
"expected": "TRXID",
"scope": "first_512_bytes",
"matched": false
}
]
}Was this page helpful?