# Run a data function

> Run one Datastruct data function and return its shaped result.

`POST /func` runs one data function. `config.data_func` accepts one function
identifier, not a list. Each function defines its own input and output contract.

## Authorization

Requires an access token and a workflow belonging to the token organization.
See [Authentication](/docs/api/data-serve/authentication/).

## Headers

| Header | Required | Description |
| --- | --- | --- |
| `X-Datastruct-Access-Token` | Conditional | Datastruct token |
| `X-Datastruct-Workflow` | Conditional | Header-token workflow |
| `Authorization` | Conditional | Alternative token header: `Bearer <token>` |
| `Content-Type` | Recommended | `application/json`; omission is accepted |

## Request body

```json
{
  "access_token": "<access-token>",
  "workflow": "wfl_01jykdqt8yejf9hz2yvcqwb4gd",
  "config": {
    "context": "prod",
    "data_func": "<data-function-id>",
    "datafunc_response_passthrough": false,
    "sources": {}
  },
  "inputs": {}
}
```

| Field | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `access_token` | string or null | No | `null` | Body token |
| `workflow` | string or null | No | `null` | Body-token workflow |
| `config` | object | Yes | — | Run configuration |
| `config.data_func` | string or null | No | `null` | `dfunc_` identifier |
| `config.context` | string | No | `dev` | `prod`, `test`, or `dev` |
| `config.sources` | object | No | `{}` | Source configuration |
| `inputs` | object | No | `{}` | Function-defined inputs |

`config.datafunc_response_passthrough` is an optional boolean with a default of
`false`. It selects the response mode defined below.

`inputs` is passed to the function without endpoint-level schema filtering.
Additional top-level fields are also passed to the function, but the endpoint
assigns no meaning to them. Do not rely on additional fields unless the
function contract defines them.

> **Confirmation needed:** Confirm how per-function input and output contracts
> will be published: individual pages, an appendix, or delivery with the
> integration.

### Credential resolution

When the workflow enables credential auto-selection, a function can select a
stored credential without a `config.sources` entry. Credentials resolve in
this order:

1. Fields in `config.sources.<source>.credentials`.
2. The stored credential named by `cred_id`.
3. An auto-selected organization credential, when enabled.
4. The organization default for the source.

See [Source configuration](/docs/api/data-serve/data-sources/) for the source
configuration object.

## Request example

```bash
curl --request POST \
  --url https://api.us.datastruct.co/func \
  --header 'Content-Type: application/json' \
  --header 'X-Datastruct-Access-Token: <access token>' \
  --header 'X-Datastruct-Workflow: wfl_01jykdqt8yejf9hz2yvcqwb4gd' \
  --data '{
    "config": {
      "context": "prod",
      "data_func": "<data-function-id>"
    },
    "inputs": {
      "address_line_1": "100 Example Avenue",
      "city": "Charlottesville",
      "state": "VA",
      "postal_code": "22901"
    }
  }'
```

> **Confirmation needed:** Replace `<data-function-id>` with an identifier
> approved for public examples. Current functions are customer or demo
> integrations.

## Standard response

Standard mode applies when `config.datafunc_response_passthrough` is `false` or
omitted.

```http
HTTP/1.1 200 OK
Content-Type: application/json
```

```json
{
  "transaction_id": "trx_01k2v8q9m7f3zb6cw4h5n0j1xd",
  "config": {
    "context": "prod",
    "data_func": "<data-function-id>",
    "datafunc_response_passthrough": false,
    "sources": {}
  },
  "outputs": {
    "<data-function-id>": {
      "output": {
        "match": true,
        "property_id": "P-4482910"
      },
      "pipes": {}
    }
  },
  "status": {
    "<data-function-id>": {
      "success": true,
      "message": "Success",
      "response_time_ms": 838
    }
  },
  "response_time_ms": 844
}
```

| Field | Type | Description |
| --- | --- | --- |
| `transaction_id` | string | Opaque `trx_` transaction identifier |
| `config` | object | Configuration with defaults |
| `outputs` | object | One function-keyed entry |
| `outputs.<func>` | object | Function-defined output |
| `status` | object | One function-keyed entry |
| `status.<func>.success` | boolean | Function completion outcome |
| `status.<func>.message` | string | Outcome text; do not parse |
| `status.<func>.response_time_ms` | integer | Function time |
| `response_time_ms` | integer | Total service time |

Function status has no `match` field. A function reports no-match inside its
own output contract.

> **Confirmation needed:** Data Serve currently adds `organization_tuid` to
> returned configuration from the access token and overwrites a client value.
> Confirm whether this internal plumbing field should remain public or be
> removed from the response contract.

## Passthrough response

Passthrough mode applies when `config.datafunc_response_passthrough` is `true`.
The function output moves to the top level, and Data Serve guarantees only
`response_time_ms`.

```json
{
  "transaction_id": "trx_01k2v8q9m7f3zb6cw4h5n0j1xd",
  "output": {
    "match": true,
    "property_id": "P-4482910"
  },
  "pipes": {},
  "response_time_ms": 844
}
```

| Field | Type | Description |
| --- | --- | --- |
| `response_time_ms` | integer | Total service time; always present |
| All other fields | any | Supplied by the data function |

Passthrough responses have no shared `status` or `config`. A failed function
returns HTTP `200` with any partial function output. The client must use the
function's own output fields to detect that failure.

Many functions return `transaction_id`, raw source results, a normalized
`output` object, and a `pipes` object. This is a convention, not a shared
contract. In a non-empty passthrough response, `transaction_id` appears only if
the function supplies it.

When a function returns no output, Data Serve returns this fixed shape:

```json
{
  "transaction_id": "trx_01k2v8q9m7f3zb6cw4h5n0j1xd",
  "output": {},
  "pipes": {},
  "response_time_ms": 12
}
```

## Function failures

All failures below appear in an HTTP `200` response.

| Message prefix | Cause |
| --- | --- |
| `Data function not found:` | Unknown function identifier |
| `Data function error:` | The function raised an error |
| `Unexpected error:` | Data Serve failed while collecting the result |

A function can report its own business failure with `success: false` and
partial output. Message wording is not a stable machine-readable code.

## Empty function identifier

A missing or empty `config.data_func` returns HTTP `200` without running a
function:

```json
{
  "transaction_id": "trx_01k2v8q9m7f3zb6cw4h5n0j1xd",
  "config": {
    "context": "dev"
  },
  "outputs": {},
  "status": {},
  "response_time_ms": 1
}
```

An empty `status` object means that no function ran. It does not mean success.

## Request errors

This endpoint can return `401`, `422`, or `500`. See
[Errors](/docs/api/data-serve/errors/) for error bodies and retry guidance.
