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

# Run a data feed transformation against a test input

> Runs a Python transformation script against the data feed's stored test input (or a file uploaded in the same request) and returns up to 3 preview rows. No events or runs are created. Real Python tracebacks are surfaced on failure, so callers can iterate write → test → save without the app's testing console. The script in `script_content` is what runs; `event_type_slug` must name an event type with an active transformation on the data feed.

If a `file` is uploaded, it replaces the data feed's stored test input. Otherwise the stored test input is used; if none exists, the request returns 422. Requires the `read:data_feed` token scope.




## OpenAPI

````yaml POST /data_feeds/{data_feed_friendly_id}/test_transformation
openapi: 3.1.0
info:
  title: Mangrove - API
  version: 1.1.0
  description: >
    ## Filtering and sorting


    List endpoints that accept `filter` take one query parameter per condition,
    written `filter[field][comparator]=value`, for example
    `filter[name][contains]=North`. The comparators are `eq`, `neq`, `gt`,
    `geq`, `lt`, `leq` and `contains`, and `filter[field]=value` is short for
    `eq`. Conditions combine with AND. `contains` matches part of the value, is
    case-sensitive, and applies only to text fields. An unknown field or
    comparator, a value that doesn't fit the field's type, or a list or object
    as the value returns 400 with a message naming the problem. Each list
    operation names its filterable fields; some take only `eq`, and say so.


    `sort` takes a comma-separated list of fields, for example
    `sort=-created_at,name`. Each field sorts ascending, or descending with a
    `-` prefix. Unknown sort fields are ignored. Sorting by `id` orders by the
    record's internal ID, not its friendly ID. Each list operation names its
    sortable fields.
servers:
  - url: https://app.gomangrove.com/api/v1
security:
  - sec0: []
paths:
  /data_feeds/{data_feed_friendly_id}/test_transformation:
    post:
      tags:
        - Data Ingestion
      summary: Run a data feed transformation against a test input
      description: >
        Runs a Python transformation script against the data feed's stored test
        input (or a file uploaded in the same request) and returns up to 3
        preview rows. No events or runs are created. Real Python tracebacks are
        surfaced on failure, so callers can iterate write → test → save without
        the app's testing console. The script in `script_content` is what runs;
        `event_type_slug` must name an event type with an active transformation
        on the data feed.


        If a `file` is uploaded, it replaces the data feed's stored test input.
        Otherwise the stored test input is used; if none exists, the request
        returns 422. Requires the `read:data_feed` token scope.
      operationId: test-data-feed-transformation
      parameters:
        - $ref: '#/components/parameters/DataFeedFriendlyId'
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - script_content
                - event_type_slug
              properties:
                script_content:
                  type: string
                  description: The Python transformation script to execute
                  example: |-
                    for row in rows:
                      events.append({'date': row['Date'], 'value': float(row['Amount'])})
                event_type_slug:
                  type: string
                  description: >-
                    The slug of an event type with an active transformation on
                    the data feed
                  example: combustion
                file:
                  type: string
                  format: binary
                  description: >-
                    Optional CSV or Excel file to use as the test input.
                    Replaces the data feed's stored test input when provided.
                    Max 50MB.
            encoding:
              file:
                contentType: >-
                  text/csv, application/vnd.ms-excel,
                  application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,
                  application/vnd.ms-excel.sheet.macroEnabled.12
      responses:
        '200':
          description: Transformation ran successfully
          content:
            application/json:
              schema:
                type: object
                required:
                  - events
                properties:
                  events:
                    type: array
                    description: Up to 3 preview rows produced by the transformation
                    items:
                      type: object
                      additionalProperties: true
                  test_input:
                    $ref: '#/components/schemas/DataFeedTestInput'
              example:
                events:
                  - date: '2024-01-01'
                    value: 100
                    unit: tCO2e
                test_input:
                  id: 42
                  filename: emissions_2024.csv
                  content_type: text/csv
                  file_size: 2048
                  uploaded_at: '2026-05-04T10:30:00Z'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: Data feed, event type, or transformation not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                dataFeedMissing:
                  value:
                    errors:
                      - message: Pipeline not found
                eventTypeMissing:
                  value:
                    errors:
                      - message: Event type 'combustion' not found
                transformationMissing:
                  value:
                    errors:
                      - message: Transformation not found for event type 'combustion'
        '422':
          description: >
            The transformation could not be executed. Either the request was
            invalid (a missing parameter, a rejected file, no test input
            available) or the Python script raised an exception. On a script
            failure, `errors` carries the humanized message, `traceback` the
            full Python traceback (or null when the failure was not a Python
            exception), and `test_input` the input it ran against.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ErrorResponse'
                  - type: object
                    properties:
                      traceback:
                        type:
                          - string
                          - 'null'
                      test_input:
                        $ref: '#/components/schemas/DataFeedTestInput'
              examples:
                missingScript:
                  summary: Missing script_content parameter
                  value:
                    errors:
                      - message: script_content is required
                missingSlug:
                  summary: Missing event_type_slug parameter
                  value:
                    errors:
                      - message: event_type_slug is required
                invalidFile:
                  summary: Uploaded file is not CSV or Excel
                  value:
                    errors:
                      - message: Only CSV and Excel files are accepted
                missingTestInput:
                  summary: No stored test input and none uploaded
                  value:
                    errors:
                      - message: Either upload a file or ensure a test input exists
                    traceback: null
                    test_input: null
                pythonError:
                  summary: Python exception raised by the script
                  value:
                    errors:
                      - message: 'KeyError: ''amount'' (line 3)'
                    traceback: |-
                      Traceback (most recent call last):
                        File "<string>", line 3, in transform
                      KeyError: 'amount'
                    test_input:
                      id: 42
                      filename: emissions_2024.csv
                      content_type: text/csv
                      file_size: 2048
                      uploaded_at: '2026-05-04T10:30:00Z'
components:
  parameters:
    DataFeedFriendlyId:
      name: data_feed_friendly_id
      in: path
      required: true
      description: The data feed's friendly ID (e.g. `datafd_aBcD1234eFgH5678`).
      schema:
        type: string
  schemas:
    DataFeedTestInput:
      type:
        - object
        - 'null'
      description: The stored test input the script ran against.
      properties:
        id:
          type: integer
        filename:
          type: string
        content_type:
          type: string
        file_size:
          type: integer
        uploaded_at:
          type: string
          format: date-time
    ErrorResponse:
      type: object
      required:
        - errors
      properties:
        errors:
          type: array
          items:
            type: object
            required:
              - message
            properties:
              message:
                type: string
                description: Human-readable error message
              field:
                type: string
                description: Attribute the error applies to (validation errors only)
              code:
                type: string
                description: Machine-readable error code (validation errors only)
              blocking:
                type: array
                description: >-
                  Bounded preview of the records blocking a destroy
                  (blocked-destroy errors only)
                items:
                  $ref: '#/components/schemas/DeletionBlockingRecord'
              blocking_count:
                type: integer
                description: >-
                  Total count of records blocking a destroy (blocked-destroy
                  errors only)
              config_key:
                type: string
                description: >-
                  The data feed source config setting to fix, when the error is
                  on `config` (data feed source validation errors only)
              count:
                type: number
                description: >-
                  The limit or comparison value the failed validation checked
                  against, e.g. a maximum length or a numeric bound (validation
                  errors only, when the validation has one)
              value:
                description: >-
                  The rejected value, e.g. on an inclusion or uniqueness failure
                  (validation errors only, when the validation reports one)
    DeletionBlockingRecord:
      type: object
      required:
        - type
      properties:
        type:
          type: string
        friendly_id:
          type: string
        name:
          type:
            - string
            - 'null'
          description: >-
            Display label, and the only identifier for records that have no
            friendly_id
  responses:
    Unauthorized:
      description: >-
        The API token is missing, invalid or expired. The body is empty, except
        for an expired token, which returns the error below.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            errors:
              - message: API token has expired
    Forbidden:
      description: >-
        The token lacks the scope the operation's description names, or a
        condition the description states applies, such as a feature that isn't
        enabled for your account.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            errors:
              - message: You are not authorized to perform this action
  securitySchemes:
    sec0:
      type: apiKey
      in: header
      name: Authorization
      x-bearer-format: ''

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.