Schemas, Destinations, and Mappings
Destination model, schema catalog, mapping resources, and downstream write-back rules for the Numora Public API developer preview.
Scope
This page defines how Numora models downstream systems and field mappings in the public API.
It covers:
- The schema catalog used as the source side of mappings
- The destination resource used for downstream systems
- The mapping resource that translates extracted fields into destination payloads
- Validation and rollout guidance based on the current app implementation
Why the Public API Uses destination
The public API should expose a stable destination-oriented model instead of leaking provider-specific internal table names.
That distinction matters because the current app implementation is still strongly shaped around Dynamics 365 and Dataverse:
- Connections are stored as provider-specific integration connections.
- Internal mapping rows are persisted per
targetTable. - The active provider today is
dynamics365.
The public contract should stay broader than the current storage model so Numora can add Salesforce, HubSpot, Excel, and other destinations without breaking the resource design.
Schema Catalog
GET /v1/schemas
The initial public schema set is:
invoice_v2receipt_v1contract_v1
Recommended response:
{
"data": [
{
"id": "invoice_v2",
"label": "Invoice",
"status": "active"
},
{
"id": "receipt_v1",
"label": "Receipt",
"status": "active"
},
{
"id": "contract_v1",
"label": "Contract",
"status": "active"
}
]
}These schema identifiers are the source side of downstream mappings.
Destination Resource
GET /v1/destinations
POST /v1/destinations
POST /v1/destinations/{id}/test
A destination represents a downstream system connection, not a single target object inside that system.
Recommended resource shape:
{
"id": "dst_01jpx4m4j2j6x9j2k6r1m9aa0v",
"provider": "dynamics365",
"display_name": "Finance Dataverse",
"status": "active",
"has_credentials": true,
"created_at": "2026-03-21T15:00:00.000Z",
"updated_at": "2026-03-21T15:05:00.000Z"
}Recommended rules:
- Credentials are write-only.
- Secrets are never returned after creation or update.
- Destination
statusshould support at leastactiveandpaused. POST /v1/destinations/{id}/testshould validate credentials and downstream reachability before the destination is used in production.
Destination Create Example
The public API should remain provider-neutral while still allowing provider-specific configuration inside the request body.
Example request:
{
"provider": "dynamics365",
"display_name": "Finance Dataverse",
"config": {
"organization_url": "https://contoso.crm.dynamics.com",
"tenant_id": "11111111-2222-3333-4444-555555555555",
"client_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"client_secret": "nr_test_123"
}
}Example response:
{
"id": "dst_01jpx4m4j2j6x9j2k6r1m9aa0v",
"provider": "dynamics365",
"display_name": "Finance Dataverse",
"status": "active",
"has_credentials": true
}Destination Test Example
For the currently active provider, the existing app behavior already validates:
- Access token acquisition
- Dataverse service-root reachability
Recommended test response:
{
"ok": true,
"provider": "dynamics365",
"organization_origin": "https://contoso.crm.dynamics.com",
"reachable": true,
"probe_status": 200
}Mapping Resource
GET /v1/mappings/{schema}/{destination}
PUT /v1/mappings/{schema}/{destination}
A public mapping resource should group all target blocks required to push one source schema into one destination.
That is broader than the current internal storage model, where separate rows are persisted per targetTable. Grouping them in one public resource gives external developers a cleaner contract.
Recommended response:
{
"schema": "invoice_v2",
"destination_id": "dst_01jpx4m4j2j6x9j2k6r1m9aa0v",
"targets": [
{
"target_object": "vendor",
"provider_object": "account",
"source_path": "$",
"field_mappings": [
{
"source": "vendor_name",
"mode": "field",
"target_field": "account.name"
},
{
"source": "invoice_total",
"mode": "field",
"target_field": "new_totalamount"
}
],
"rules": {
"push_on_reviewed": true,
"require_approval": false
}
}
],
"updated_at": "2026-03-21T15:18:00.000Z"
}Field Mapping Model
Each mapping row should support:
sourcemodeexpressiontarget_fieldrequired
Recommended semantics:
mode = fieldmeans the value comes from a structured extraction field.mode = custommeans the value is computed from a controlled expression.source_path = "$"means the mapping reads from the document-level result.source_path = "$.lineItems[*]"means the mapping iterates over extracted line items.
For line-item mappings, a target block may also need:
parent_target_objectparent_lookup_field
Those fields allow the downstream payload to bind child rows back to the parent object created earlier in the same push run.
Validation Rules
The public contract should validate mappings before they are activated.
Recommended checks:
- The requested schema must be supported.
- The target object must be inside the destination scope.
- Target fields must be accessible for the destination.
- Required source fields should be mapped for document-level targets.
- Duplicate target fields should surface a warning.
- Empty mapping definitions should be rejected.
The current app already implements most of this validation logic internally for target-table scope, required source rows, and duplicate target-field warnings.
Current Availability
The provider registry in the app currently indicates:
dynamics365: activesalesforce: plannedhubspot: plannedexcel: planned
That means the first public destination rollout should document dynamics365 as the active destination provider and treat the others as future additions rather than already available integrations.
Rollout Guidance
Recommended order:
- Ship
GET /v1/schemas. - Ship destination create/list/test for
dynamics365. - Ship
GET/PUT /v1/mappings/{schema}/{destination}. - Add mapping validation and test endpoints.
- Only then expand to additional providers.