Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Bem Functions API
version: 1.0.0
description: 'Functions are the core building blocks of data transformation in Bem. Each function type serves a specific purpose:
- **Extract**: Extract structured JSON data from unstructured documents (PDFs, emails, images, spreadsheets), with optional layout-aware bounding-box extraction
- **Route**: Direct data to different processing paths based on conditions
- **Split**: Break multi-page documents into individual pages for parallel processing
- **Join**: Combine outputs from multiple function calls into a single result
- **Parse**: Render documents into a navigable structure of page-aware sections, named entities, and relationships — designed to be walked by an LLM agent via the [File System API](/api/v3/file-system) (`POST /v3/fs`). Two toggles, both `true` by default: `extractEntities` controls per-document entity and relationship extraction; `linkAcrossDocuments` merges entities into one canonical record per real-world thing across the environment, populating cross-document memory.
- **Payload Shaping**: Transform and restructure data using JMESPath expressions
- **Enrich**: Enhance data with semantic search against collections
- **Send**: Deliver workflow outputs to downstream destinations
Use these endpoints to create, update, list, and manage your functions.'
servers:
- url: https://api.bem.ai
description: US Region API
variables: {}
- url: https://api.eu1.bem.ai
description: EU Region API
variables: {}
security:
- API Key: []
tags:
- name: Functions
description: 'Functions are the core building blocks of data transformation in Bem. Each function type serves a specific purpose:
- **Extract**: Extract structured JSON data from unstructured documents (PDFs, emails, images, spreadsheets), with optional layout-aware bounding-box extraction
- **Route**: Direct data to different processing paths based on conditions
- **Split**: Break multi-page documents into individual pages for parallel processing
- **Join**: Combine outputs from multiple function calls into a single result
- **Parse**: Render documents into a navigable structure of page-aware sections, named entities, and relationships — designed to be walked by an LLM agent via the [File System API](/api/v3/file-system) (`POST /v3/fs`). Two toggles, both `true` by default: `extractEntities` controls per-document entity and relationship extraction; `linkAcrossDocuments` merges entities into one canonical record per real-world thing across the environment, populating cross-document memory.
- **Payload Shaping**: Transform and restructure data using JMESPath expressions
- **Enrich**: Enhance data with semantic search against collections
- **Send**: Deliver workflow outputs to downstream destinations
Use these endpoints to create, update, list, and manage your functions.'
paths:
/v3/functions:
post:
operationId: v3-create-function
summary: Create a Function
description: '**Create a function.**
The function `type` determines which configuration fields are
required — see the `CreateFunctionV3` discriminated union and
[Function types overview](/guide/function-types/overview) for the
per-type contract.
The response contains both `functionID` and `functionName`. Either is
a stable handle you can use elsewhere; most workflows reference
functions by `functionName` because it''s human-readable.
## Naming rules
- `functionName` must be unique per environment.
- Allowed characters: letters, digits, hyphens, and underscores.
- Names cannot be reused after deletion within the same environment
for at least the retention window of the previous record.
The new function is created at `versionNum: 1`. Subsequent
`PATCH /v3/functions/{functionName}` calls produce new versions —
the version-1 configuration remains immutable and addressable.'
parameters: []
responses:
'200':
description: The request has succeeded.
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionResponseV3'
tags:
- Functions
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateFunctionV3'
get:
operationId: v3-list-functions
summary: List Functions
description: '**List functions in the current environment.**
Returns each function''s current version. Combine filters freely —
they AND together.
## Filtering
- `functionIDs` / `functionNames`: exact-match identity filters.
- `displayName`: case-insensitive substring match.
- `types`: one or more of `extract`, `classify`, `split`, `join`,
`enrich`, `payload_shaping`. Legacy `transform`, `analyze`, `route`,
and `send` types remain readable via this filter.
- `tags`: returns functions tagged with any of the supplied tags.
- `workflowIDs` / `workflowNames`: returns only functions referenced
by the named workflows. Useful for "what functions does this
workflow depend on?" lookups.
## Pagination
Cursor-based with `startingAfter` and `endingBefore` (functionIDs).
Default limit 50, maximum 100.'
parameters:
- name: limit
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 100
default: 50
- name: functionIDs
in: query
required: false
schema:
type: array
items:
type: string
minItems: 1
explode: false
- name: functionNames
in: query
required: false
schema:
type: array
items:
type: string
minItems: 1
explode: false
- name: displayName
in: query
required: false
schema:
type: string
explode: false
- name: types
in: query
required: false
schema:
type: array
items:
$ref: '#/components/schemas/FunctionType'
minItems: 1
explode: false
- name: sortOrder
in: query
required: false
schema:
type: string
enum:
- asc
- desc
default: asc
- name: startingAfter
in: query
required: false
schema:
type: string
- name: endingBefore
in: query
required: false
schema:
type: string
- name: tags
in: query
required: false
schema:
type: array
items:
type: string
minItems: 1
explode: false
- name: workflowIDs
in: query
required: false
schema:
type: array
items:
type: string
minItems: 1
explode: false
- name: workflowNames
in: query
required: false
schema:
type: array
items:
type: string
minItems: 1
explode: false
responses:
'200':
description: The request has succeeded.
content:
application/json:
schema:
$ref: '#/components/schemas/ListFunctionsResponseV3'
tags:
- Functions
/v3/functions/copy:
post:
operationId: v3-copy-function
summary: Copy a Function
description: '**Copy a function to a new name within the same environment.**
Forks the source function''s current configuration into a brand-new
function. The copy starts at `versionNum: 1` regardless of how many
versions the source has — version history is not carried over.
Useful for experimenting with schema or prompt changes against a
stable production function without disturbing existing callers.
The destination name must be unique in the environment. A copy does
not migrate workflows: existing workflow nodes continue to reference
the original function.'
parameters: []
responses:
'200':
description: The request has succeeded.
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionResponseV3'
'400':
description: The server could not understand the request due to invalid syntax.
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPError'
tags:
- Functions
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionCopyRequest'
/v3/functions/{functionName}:
delete:
operationId: v3-delete-function
summary: Delete a Function
description: '**Delete a function and every one of its versions.**
Permanent. Running and queued calls that reference this function
continue to completion against the version they captured at call
time, but no new calls can target it.
## Before deleting
Workflow nodes that reference this function will fail at call time
after deletion. List workflows that reference it first:
```
GET /v3/workflows?functionNames=my-function
```
Update or remove those workflows, or create a replacement function
and re-point the workflow nodes, before deleting.'
parameters:
- name: functionName
in: path
required: true
schema:
type: string
responses:
'204':
description: 'There is no content to send for this request, but the headers may be useful. '
tags:
- Functions
get:
operationId: v3-get-function
summary: Get a Function
description: '**Retrieve a function''s current version by name.**
Returns the function record with its `currentVersionNum` and the
configuration of that version. To inspect a historical version, use
`GET /v3/functions/{functionName}/versions/{versionNum}`.'
parameters:
- name: functionName
in: path
required: true
schema:
type: string
responses:
'200':
description: The request has succeeded.
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionResponseV3'
tags:
- Functions
patch:
operationId: v3-update-function
summary: Update a Function
description: '**Update a function. Updates create a new version.**
The previous version remains addressable and immutable. Workflow
nodes that pinned the function with a `versionNum` continue to use
the pinned version; nodes that reference the function by name with
no version automatically pick up the new version on their next call.
## What you can change
Any field allowed by the function''s type. Most commonly:
`outputSchema` (for `extract`/`join`), `classifications` (for
`classify`), `displayName`, and `tags`.
## Versioning behaviour
- Each successful update increments `currentVersionNum` by 1.
- `displayName`, `tags`, and `functionName` updates also create a
new version, so the version history is a complete record of every
change.
- To revert, fetch the previous version and re-submit its
configuration as a new update — versions themselves are immutable.'
parameters:
- name: functionName
in: path
required: true
schema:
type: string
x-stainless-param: path_function_name
x-stainless-param: path_function_name
responses:
'200':
description: The request has succeeded.
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionResponseV3'
tags:
- Functions
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateFunctionV3'
/v3/functions/{functionName}/versions:
get:
operationId: v3-list-function-versions
summary: List Function Versions
description: '**List every version of a function.**
Returns the full version history, newest-first. Each row captures
the configuration the function had between updates. Useful for
audits ("when did this schema change?") and for diffing two
versions before promoting an update to production.'
parameters:
- name: functionName
in: path
required: true
schema:
type: string
responses:
'200':
description: The request has succeeded.
content:
application/json:
schema:
$ref: '#/components/schemas/ListFunctionVersionsResponseV3'
tags:
- Functions
/v3/functions/{functionName}/versions/{versionNum}:
get:
operationId: v3-get-function-version
summary: Get a Function Version
description: '**Retrieve a specific historical version of a function.**
Versions are immutable. Use this endpoint to inspect what a function
looked like at the moment a particular call was made — every event
and transformation records the function version it ran against.'
parameters:
- name: functionName
in: path
required: true
schema:
type: string
- name: versionNum
in: path
required: true
schema:
type: integer
responses:
'200':
description: The request has succeeded.
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionVersionResponseV3'
tags:
- Functions
components:
schemas:
CreateParseFunction:
type: object
required:
- functionName
- type
properties:
functionName:
type: string
description: Name of function. Must be UNIQUE on a per-environment basis.
displayName:
type: string
description: Display name of function. Human-readable name to help you identify the function.
tags:
type: array
items:
type: string
description: Array of tags to categorize and organize functions.
type:
type: string
enum:
- parse
parseConfig:
$ref: '#/components/schemas/ParseConfig'
extraConfig:
$ref: '#/components/schemas/ParseExtraFunctionConfiguration'
title: Parse Function
SendDestinationType:
type: string
enum:
- webhook
- s3
- google_drive
description: Destination type for a Send function.
AnalyzeFunctionVersion:
type: object
required:
- functionID
- functionName
- versionNum
- type
- outputSchemaName
- outputSchema
- enableBoundingBoxes
- preCount
properties:
functionID:
type: string
description: Unique identifier of function.
functionName:
type: string
description: Name of function. Must be UNIQUE on a per-environment basis.
versionNum:
type: integer
description: Version number of function.
usedInWorkflows:
type: array
items:
$ref: '#/components/schemas/WorkflowUsageInfo'
description: List of workflows that use this function.
displayName:
type: string
description: Display name of function. Human-readable name to help you identify the function.
tags:
type: array
items:
type: string
description: Array of tags to categorize and organize functions.
createdAt:
type: string
format: date-time
description: The date and time the function version was created.
audit:
allOf:
- $ref: '#/components/schemas/FunctionAudit'
description: Audit trail information for the function version.
type:
type: string
enum:
- analyze
outputSchemaName:
type: string
description: Name of output schema object.
outputSchema:
type: object
unevaluatedProperties: {}
description: Desired output structure defined in standard JSON Schema convention.
enableBoundingBoxes:
type: boolean
description: 'Whether bounding box extraction is enabled. Only applicable to analyze and extract functions.
When true, the function returns the document regions (page, coordinates) from which each
field was extracted.'
preCount:
type: boolean
description: 'Reducing the risk of the model stopping early on long documents.
Trade-off: Increases total latency.'
CreateEnrichFunction:
type: object
required:
- functionName
- type
properties:
functionName:
type: string
description: Name of function. Must be UNIQUE on a per-environment basis.
displayName:
type: string
description: Display name of function. Human-readable name to help you identify the function.
tags:
type: array
items:
type: string
description: Array of tags to categorize and organize functions.
config:
$ref: '#/components/schemas/enrichConfig'
type:
type: string
enum:
- enrich
title: Enrich Function
UpsertEnrichFunction:
type: object
required:
- type
properties:
config:
$ref: '#/components/schemas/enrichConfig'
type:
type: string
enum:
- enrich
ParseConfig:
type: object
properties:
extractEntities:
type: boolean
description: 'When true, extract named entities (people, organizations, products,
studies, identifiers, etc.) and the relationships between them, and
dedupe by canonical name within the document. When false, only
`sections[]` is extracted; `entities[]` and `relationships[]` come
back empty in the parse output. Defaults to true.'
linkAcrossDocuments:
type: boolean
description: 'When true, link this document''s entities to entities seen in earlier
documents in this environment, building one canonical record per
real-world thing across the corpus. Visible in the Memory tab and
queryable via `POST /v3/fs` (op=find / open / xref). Doesn''t change
this call''s parse output. Requires `extractEntities=true`. Defaults
to true.'
schema:
type: object
unevaluatedProperties: {}
description: 'Optional JSONSchema. When provided, each chunk performs schema-guided
extraction. When absent, chunks perform open-ended discovery and
return sections, entities, and relationships per the discovery
schema.'
defaultBucket:
type: string
description: 'Optional bucket NAME that parse-extracted entities land in when no
call-level bucket is supplied. Lower precedence than a call-level bucket,
higher than the account+environment default.'
description: 'Per-version configuration for a Parse function.
Parse renders document pages (PDF, image) via vision LLM and emits
structured JSON. The two toggles below independently control entity
extraction (a per-call output concern) and cross-document memory
linking (an environment-wide concern).'
ParseFunctionVersion:
type: object
required:
- functionID
- functionName
- versionNum
- type
properties:
functionID:
type: string
description: Unique identifier of function.
functionName:
type: string
description: Name of function. Must be UNIQUE on a per-environment basis.
versionNum:
type: integer
description: Version number of function.
usedInWorkflows:
type: array
items:
$ref: '#/components/schemas/WorkflowUsageInfo'
description: List of workflows that use this function.
displayName:
type: string
description: Display name of function. Human-readable name to help you identify the function.
tags:
type: array
items:
type: string
description: Array of tags to categorize and organize functions.
createdAt:
type: string
format: date-time
description: The date and time the function version was created.
audit:
allOf:
- $ref: '#/components/schemas/FunctionAudit'
description: Audit trail information for the function version.
type:
type: string
enum:
- parse
parseConfig:
$ref: '#/components/schemas/ParseConfig'
extraConfig:
$ref: '#/components/schemas/ParseExtraFunctionConfiguration'
UpdateFunctionV3:
type: object
oneOf:
- $ref: '#/components/schemas/UpsertExtractFunction'
- $ref: '#/components/schemas/UpsertClassifyFunction'
- $ref: '#/components/schemas/UpsertSendFunction'
- $ref: '#/components/schemas/UpsertSplitFunction'
- $ref: '#/components/schemas/UpsertJoinFunction'
- $ref: '#/components/schemas/UpsertPayloadShapingFunction'
- $ref: '#/components/schemas/UpsertEnrichFunction'
- $ref: '#/components/schemas/UpsertParseFunction'
- $ref: '#/components/schemas/UpsertRenderFunction'
discriminator:
propertyName: type
mapping:
extract: '#/components/schemas/UpsertExtractFunction'
classify: '#/components/schemas/UpsertClassifyFunction'
send: '#/components/schemas/UpsertSendFunction'
split: '#/components/schemas/UpsertSplitFunction'
join: '#/components/schemas/UpsertJoinFunction'
payload_shaping: '#/components/schemas/UpsertPayloadShapingFunction'
enrich: '#/components/schemas/UpsertEnrichFunction'
parse: '#/components/schemas/UpsertParseFunction'
render: '#/components/schemas/UpsertRenderFunction'
CreateFunctionV3:
type: object
oneOf:
- $ref: '#/components/schemas/CreateExtractFunction'
- $ref: '#/components/schemas/CreateClassifyFunction'
- $ref: '#/components/schemas/CreateSendFunction'
- $ref: '#/components/schemas/CreateSplitFunction'
- $ref: '#/components/schemas/CreateJoinFunction'
- $ref: '#/components/schemas/CreatePayloadShapingFunction'
- $ref: '#/components/schemas/CreateEnrichFunction'
- $ref: '#/components/schemas/CreateParseFunction'
- $ref: '#/components/schemas/CreateRenderFunction'
discriminator:
propertyName: type
mapping:
extract: '#/components/schemas/CreateExtractFunction'
classify: '#/components/schemas/CreateClassifyFunction'
send: '#/components/schemas/CreateSendFunction'
split: '#/components/schemas/CreateSplitFunction'
join: '#/components/schemas/CreateJoinFunction'
payload_shaping: '#/components/schemas/CreatePayloadShapingFunction'
enrich: '#/components/schemas/CreateEnrichFunction'
parse: '#/components/schemas/CreateParseFunction'
render: '#/components/schemas/CreateRenderFunction'
enrichEndpoint:
type: object
required:
- name
- url
- method
properties:
name:
type: string
description: Unique name for this endpoint, referenced by enrichStep.endpointName.
url:
type: string
description: Full URL of the endpoint (must be http:// or https://).
method:
type: string
enum:
- GET
- POST
description: HTTP method to use.
headers:
type: object
unevaluatedProperties:
type: string
description: 'Additional HTTP headers to include in every request (e.g. `Authorization: Bearer <token>`).'
queryParam:
type: string
description: 'Query parameter name used to pass the extracted source value.
**Required for GET endpoints.** The value is URL-encoded and appended as `?{queryParam}={sourceValue}`.
Example: `queryParam: "q"` → `GET /products?q=blue+widget`'
bodyTemplate:
type: string
description: 'JSON body template for POST requests.
**Required for POST endpoints.** Must contain the `{value}` placeholder, which is replaced
with the extracted source value at runtime.
Example: `bodyTemplate: "{\"query\": \"{value}\", \"limit\": 10}"`'
responsePath:
type: string
description: 'JMESPath expression applied to the response body to extract the enrichment value.
Omit to use the entire response body as the result.
**For agent reasoning:** use a wildcard projection (e.g. `items[*]` or `results[*].data`)
so the endpoint''s list of candidates is flattened into an array before being passed to the LLM.
A non-wildcard path (e.g. `data.product`) extracts a single value treated as one candidate.
**Response size:** the platform reads at most 50 MB of the response body before decoding,
regardless of the Content-Length header.'
matchInstructions:
type: string
description: 'Natural-language instructions for LLM agent reasoning.
When set, the candidates fetched from the endpoint are passed to an LLM with these
instructions, which selects the best match(es) and returns them with confidence scores.
Each injected result has the shape `{ data, confidence, reasoning? }`.
When omitted, the raw fetched value is injected without any LLM involvement.'
matchTopK:
type: integer
minimum: 1
maximum: 100
description: 'Maximum number of ranked matches to return per source value when `matchInstructions`
is set (default: 1). Ignored when `matchInstructions` is empty.'
default: 1
maxCandidates:
type: integer
minimum: 1
description: 'LLM batch size during agent reasoning (default: 50). All candidates — across all
fetched pages — are scored in batches of this size. Smaller values reduce per-call
token usage; larger values mean fewer LLM calls. Ignored when `matchInstructions`
is empty.'
default: 50
nextPagePath:
type: string
description: 'JMESPath expression applied to each raw response to extract the cursor or token
for the next page (e.g. `"nextCursor"`, `"pagination.nextToken"`). An absent,
null, or empty-string result stops pagination. Both string and numeric values are
supported — numbers are converted to their decimal string representation before
being forwarded as a query parameter.
Must be set together with `nextPageParam`.
**Supported pagination styles:**
- **Cursor/token-based** — server returns an opaque token in the response body
(e.g. `{"nextCursor": "abc123"}`). Set `nextPagePath: "nextCursor"` and the
platform forwards it verbatim on the next request.
- **Server-computed offset/page** — server echoes back the next offset or page
number in the response body (e.g. `{"nextOffset": 50}` or `{"nextPage": 2}`).
Set `nextPagePath: "nextOffset"` and the platform forwards the value as-is.
**Not supported:**
- **Client-computed offset** — APIs where the client must compute `offset += limit`
itself (e.g. `?offset=0&limit=50` with no next-offset in the response). Workaround:
ask the API provider to return the next offset in the response body, or bake a
fixed page size into the URL and use a server-side cursor instead.
- **Client-computed page number** — APIs where the client increments `?page=N`
itself with no next-page value in the response. Same workaround applies.
- **Link header** — `Link: <url>; rel="next"` in HTTP response headers. The
platform only inspects the response body.'
nextPageParam:
type: string
description: 'Query parameter name used to pass the cursor on subsequent GET requests, or the
`{placeholder}` name used in the POST `bodyTemplate` (e.g. `"cursor"`,
`"pageToken"`, `"offset"`).
Must be set together with `nextPagePath`.'
maxPages:
type: integer
minimum: 1
description: 'Maximum number of pages to fetch (default: 10). Acts as a safety cap against
infinite pagination loops when the server never returns an empty cursor.'
default: 10
description: 'A named HTTP endpoint that an enrich step can call to fetch enrichment data.
The platform makes one request per extracted source value, substituting the value
as a query parameter or body template placeholder. The raw response (or the
sub-value selected by `responsePath`) is injected into the output, or passed to
LLM agent reasoning when `matchInstructions` is set.
**Request formats:**
- `GET`: Appends `?{queryParam}={value}` to the URL.
- `POST`: Sends `bodyTemplate` as the request body, replacing `{value}` with the extracted value.'
FunctionVersionV3:
type: object
oneOf:
- $ref: '#/components/schemas/TransformFunctionVersion'
- $ref: '#/components/schemas/ExtractFunctionVersion'
- $ref: '#/components/schemas/AnalyzeFunctionVersion'
- $ref: '#/components/schemas/ClassifyFunctionVersion'
- $ref: '#/components/schemas/SendFunctionVersion'
- $ref: '#/components/schemas/SplitFunctionVersion'
- $ref: '#/components/schemas/JoinFunctionVersion'
- $ref: '#/components/schemas/EnrichFunctionVersion'
- $ref: '#/components/schemas/PayloadShapingFunctionVersion'
- $ref: '#/components/schemas/ParseFunctionVersion'
- $ref: '#/components/schemas/RenderFunctionVersion'
discriminator:
propertyName: type
mapping:
transform: '#/components/schemas/TransformFunctionVersion'
extract: '#/components/schemas/ExtractFunctionVersion'
analyze: '#/components/schemas/AnalyzeFunctionVersion'
classify: '#/components/schemas/ClassifyFunctionVersion'
send: '#/components/schemas/SendFunctionVersion'
split: '#/components/schemas/SplitFunctionVersion'
join: '#/components/schemas/JoinFunctionVersion'
enrich: '#/components/schemas/EnrichFunctionVersion'
payload_shaping: '#/components/schemas/PayloadShapingFunctionVersion'
parse: '#/components/schemas/ParseFunctionVersion'
render: '#/components/schemas/RenderFunctionVersion'
description: 'V3 read-side union for function versions. Same shape as the shared
`FunctionVersion` union but with `classify` in place of `route`.'
FunctionAudit:
type: object
properties:
functionCreatedBy:
allOf:
- $ref: '#/components/schemas/UserActionSummary'
description: Information about who created the function.
functionLastUpdatedBy:
allOf:
- $ref: '#/components/schemas/UserAction
# --- truncated at 32 KB (109 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/bem/refs/heads/main/openapi/bem-functions-api-openapi.yml