> ## Documentation Index
> Fetch the complete documentation index at: https://docs.structural.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Transform data

> Stateless translation: pass in platform data, get back the canonical form and the
target platform's representation. Nothing is persisted. Use this to preview a
translation before committing with `/propagate`.


The stateless translation primitive. Pass in platform data, get back the canonical form
and the target platform's representation. **Nothing is persisted** - no database reads or
writes, no fan-out to connected platforms.

Use `/transform` when you want to:

* Preview what a cross-platform translation looks like before committing with
  [`POST /propagate`](/api-reference/propagate)
* Validate your data shape against Structural's canonical model
* Get both the canonical and target-platform views in a single call without side effects

## Supported entity types

`/transform` accepts **9 entity types** - more than `/connect` and `/propagate` (which
accept 5), because it does not require entity data to be seeded first:

`project`, `customer`, `contract`, `invoice`, `payment`, `employee`, `time_entry`,
`change_order`, `budget_line_item`

## The context field

Some mappers require additional context that is not present in the source data itself. The
`context` field is an optional generic object (`Record<string, unknown>`) that passes
through to the mapper.

**Procore contracts** require `context` with a `commitmentType` key:

```json theme={null}
{
  "source": "procore",
  "target": "dynamics",
  "entity_type": "contract",
  "data": {
    "id": 1945782,
    "title": "Substructure Package",
    "number": "C-LEX-001",
    "status": "Approved",
    "grand_total": "8500000.00",
    "project": { "id": 341276, "name": "Lusail Boulevard Tower" },
    "vendor": { "id": 501004, "company": "Doha Infrastructure Partners WLL" },
    "description": "Raft foundation and basement levels",
    "contract_start_date": "2025-11-01",
    "contract_estimated_completion_date": "2026-06-30",
    "currency_configuration": { "currency_iso_code": "USD" }
  },
  "context": {
    "commitmentType": "WorkOrderContract"
  }
}
```

Valid values for `commitmentType` are `"WorkOrderContract"` and `"PurchaseOrderContract"`.
Omitting `context` when transforming a Procore contract results in a `422 TRANSFORM_ERROR`.

Dynamics contracts do not require `context` - the mapper handles them without additional
input.

## Response

The response contains three sections:

* **`canonical`** - the platform-agnostic representation with typed IDs, money in minor
  units, and ISO currency codes
* **`data`** - the target platform's representation, ready to send to that platform's API
* **`metadata`** - source, target, entity type, canonical version, timestamp, and request
  ID. When cross-entity references were resolved (e.g., a payment referencing a project),
  a `references` object reports which references were resolved and which could not be
  found


## OpenAPI

````yaml POST /transform
openapi: 3.1.0
info:
  title: Structural API
  version: '1.0'
  description: |
    Bidirectional data translation between construction management platforms.
    One integration gives you normalized access to every connected platform.
  contact:
    email: support@structural.app
    url: https://structural.app
servers:
  - url: https://api.structural.app/api/v1
    description: Production
security: []
paths:
  /transform:
    post:
      tags:
        - Transform
      summary: Transform data
      description: >
        Stateless translation: pass in platform data, get back the canonical
        form and the

        target platform's representation. Nothing is persisted. Use this to
        preview a

        translation before committing with `/propagate`.
      operationId: transformData
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TransformRequest'
      responses:
        '200':
          description: Data transformed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransformResult'
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '422':
          $ref: '#/components/responses/TransformError'
      security:
        - bearerAuth: []
components:
  schemas:
    TransformRequest:
      type: object
      required:
        - source
        - target
        - entity_type
        - data
      properties:
        source:
          type: string
          enum:
            - procore
            - dynamics
          description: Source platform
        target:
          type: string
          enum:
            - procore
            - dynamics
          description: Target platform
        entity_type:
          type: string
          enum:
            - project
            - customer
            - employee
            - time_entry
            - invoice
            - payment
            - contract
            - change_order
            - budget_line_item
          description: >
            The entity type to transform. 9 types are supported. `contract`
            requires a

            `context` field when `source` is `procore`.
        data:
          type: object
          description: The platform-native data to transform
          additionalProperties: true
        context:
          type: object
          description: >
            Optional mapper context. For Procore contracts, pass

            `{"commitmentType": "WorkOrderContract"}` or `{"commitmentType":
            "PurchaseOrderContract"}`.

            Omitting this for Procore contracts results in a 422 error.
          additionalProperties: true
    TransformResult:
      type: object
      properties:
        canonical:
          type: object
          description: The canonical (normalized) representation
          additionalProperties: true
        data:
          type: object
          description: The target platform's representation
          additionalProperties: true
        metadata:
          type: object
          properties:
            source:
              type: string
              enum:
                - procore
                - dynamics
            target:
              type: string
              enum:
                - procore
                - dynamics
            entity_type:
              type: string
            canonical_version:
              type: string
              example: '1.0'
            transformed_at:
              type: string
              format: date-time
            request_id:
              type: string
              example: req_a1b2c3d4e5f6
            references:
              type: object
              description: Present when cross-entity references were resolved
              properties:
                resolved:
                  type: array
                  items:
                    type: object
                    properties:
                      field:
                        type: string
                      canonical_id:
                        type: string
                      platform_id:
                        type: string
                      injected:
                        type: boolean
                      reason:
                        type: string
                unresolved:
                  type: array
                  items:
                    type: object
                    properties:
                      field:
                        type: string
                      canonical_id:
                        type: string
                      reason:
                        type: string
    ErrorResponse:
      type: object
      properties:
        error:
          type: object
          required:
            - type
            - message
            - request_id
          properties:
            type:
              type: string
              description: Machine-readable error code
              example: VALIDATION_ERROR
            message:
              type: string
              description: Human-readable error description
              example: platform and entity_type query params required
            request_id:
              type: string
              description: Unique request identifier — quote this in support requests
              example: req_a1b2c3d4e5f6
  responses:
    ValidationError:
      description: Request validation failed
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              type: VALIDATION_ERROR
              message: Invalid input
              request_id: req_a1b2c3d4e5f6
    AuthenticationError:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              type: AUTHENTICATION_ERROR
              message: Invalid or missing API key
              request_id: req_a1b2c3d4e5f6
    TransformError:
      description: Transform failed (e.g., missing context for Procore contracts)
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              type: TRANSFORM_ERROR
              message: Transform failed
              request_id: req_a1b2c3d4e5f6
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >
        API key passed as a Bearer token. Keys are prefixed: `sk_demo_*`
        (sandbox),

        `sk_live_*` (production), `sk_test_*` (staging).

````