OpenAPI Apps
OpenAPI apps let you connect Studio to any HTTP API and use it from Actions as either inputs (steps that fetch data) or tools (operations an Agent step or Tool Call step can invoke). You can populate the app from an OpenAPI specification or define inputs and tools by hand.
For a general overview of all app types, see Tenant Admin > Apps.
What an OpenAPI App Provides
An OpenAPI app contributes three kinds of resources to Actions:
- Inputs — fetch data from the API at the start of a step. The result lands in the step's input parameters.
- Tools — callable operations the LLM can pick from inside an Agent step, or you can invoke directly from a Tool Call step.
- Webhook trigger — an optional, opt-in HTTP endpoint that external systems can call to start an Action.
Each input or tool stores:
- A name and a description.
- A Configuration Template that describes the HTTP request (base URL, method, path, headers, body shape, defaults).
- A Parameters Schema (JSON Schema) that describes the parameters the user, the LLM, or an earlier step will supply at runtime.
- An optional Sample Response in JSON format.
Creating an OpenAPI App
- Go to Tenant Admin > Apps.
- Select New, choose OpenAPI, and continue.
- Enter a name and save the app.
- Open the saved app and select Configure Credentials, choosing the authentication type that matches the target API:
- None — public APIs that need no credentials.
- API Key — a single shared key, referenced from the configuration template via the
{{APP_API_KEY}}or{{APP_API_KEY_BASE64}}placeholder. - OAuth 2.0 Client Credentials — a Service Principal flow. Studio acquires and caches a bearer token, which you reference via
{{APP_BEARER_TOKEN}}.
After credentials are saved, populate the app with inputs and tools using either of the two methods below.
Populating the App
Option 1: Import from an OpenAPI Specification
Studio can read an OpenAPI 2.0 or 3.x specification in JSON or YAML and generate inputs or tools for the operations it contains.
- Open the app.
- On the Inputs or Tools tab, select Import from OpenAPI.
- Provide the spec by one of:
- Entering the URL of a hosted spec (Studio fetches it).
- Pasting raw JSON or YAML.
- Uploading a
.json,.yaml,.yml, or.txtfile.
- Review the parsed operations. Each operation shows its name, method, path, parameters, and a preview of any example responses found in the spec.
- Select which operations to import as inputs (or tools — you choose the resource type per import) and confirm.
For each imported operation Studio generates a Configuration Template, a Parameters Schema, and a Sample Response (when the spec contains an example). You can edit any of those after import.
There is no automatic rule that decides whether an operation should be an input or a tool — you pick the resource type in the dialog. As a guideline:
- Use inputs for operations that read data the Action Flow needs before reasoning starts, such as fetching an entity by ID at the start of a step.
- Use tools for operations the Agent should be able to decide to call, or that you want to invoke from a Tool Call step.
Option 2: Define Inputs and Tools Manually
- Open the app and go to the Inputs or Tools tab.
- Select New.
- Fill in name, description, and tags.
- Edit the Configuration Template, the Parameters Schema, and optionally the Sample Response.
- Save.
Both options produce the same kind of resource — an imported input or tool can be edited by hand afterwards, and you can mix imported and hand-written resources within a single app.
Configuration Template
The Configuration Template is JSON that describes the HTTP request. The recognised fields are:
| Field | Purpose |
|---|---|
BaseUrl | Required base URL of the API. |
Method | HTTP verb. Defaults to GET. |
Path | URL path. May contain {paramName} placeholders for path parameters. |
Headers | Static headers added to every request. Values support placeholders. |
Query | Static query string parameters. Values support placeholders. |
RequestContentType | Content-Type for the request body. Defaults to application/json. |
BodyMode | How the body is encoded: json, raw, or multipartFormData. Auto-detected from RequestContentType when omitted. |
Body | A static request body, used when a runtime body parameter is not supplied. |
BinaryFormFields | For multipartFormData: the names of fields whose values should be uploaded as files. |
MultipartFileNames, MultipartFileContentTypes | Per-field filename and content type overrides for multipart uploads. |
DefaultParameterValues | Per-parameter fallback values. Used when a runtime parameter is missing or empty. |
ParametersSchema | The JSON Schema of the parameters. Only for inputs — for tools the schema lives in a separate editor (see below). |
Example: A Simple GET Input
This is the default template Studio gives you when you create a new OpenAPI input:
{
"BaseUrl": "https://sample-site.com",
"Method": "GET",
"Path": "/api/v1/example/invoices/{invoiceid}",
"Headers": {
"Authorization": "Bearer {{APP_BEARER_TOKEN}}",
"x-example-custom-header": "your_value"
},
"DefaultParameterValues": {
"invoiceid": "{{inputs.dooapEventPayload.dooapInvoiceId}}"
}
}
This input reads an invoice by ID. The bearer token is injected from the app credentials. The default for invoiceid is read from the trigger payload, so the user does not have to fill it in for Dooap-triggered Actions.
Example: A GET Input with Parameter Schema
{
"BaseUrl": "https://api.example.com",
"Method": "GET",
"Path": "/api/vendors/{vendorId}",
"Headers": {
"Authorization": "Bearer {{APP_BEARER_TOKEN}}"
},
"ParametersSchema": {
"type": "object",
"properties": {
"vendorId": { "type": "string", "description": "The unique identifier of the vendor" },
"includeDetails": { "type": "string", "description": "Whether to include additional vendor details" }
},
"required": ["vendorId"],
"additionalProperties": false,
"x-parameter-locations": {
"vendorId": "path",
"includeDetails": "query"
}
},
"DefaultParameterValues": {
"vendorId": "{{inputs.dooapEventPayload.dooapVendorId}}"
}
}
The same parameters dictionary supplies path, query, header, and body values. Where each parameter is sent is controlled by x-parameter-locations (see below).
Parameters Schema
The Parameters Schema is a JSON Schema that describes the runtime parameters the input or tool expects. The same schema serves three purposes:
- It renders the parameter form the user sees in the input configuration view or in a Tool Call step.
- It tells Studio how to route each parameter (path, query, header, or body) into the HTTP request.
- For tools, it defines the function signature the LLM sees inside an Agent step.
For inputs, the schema is embedded in the Configuration Template under ParametersSchema. For tools, the schema lives in a separate editor next to the Configuration Template, because tools also surface this schema to the LLM.
Studio supports standard JSON Schema (type, properties, required, enum, description, default, items, additionalProperties, and so on), plus these Dooap-specific extensions:
x-parameter-locations
A map from property name to where the value is sent in the HTTP request:
"x-parameter-locations": {
"vendorId": "path",
"includeDetails": "query",
"X-Trace-Id": "header",
"items": "body"
}
Allowed locations are path, query, header, and body. The configuration view shows each location as a small chip next to the parameter name.
x-reference
A per-property hint that the value should be picked through a Studio picker instead of typed as free text:
| Value | Renders as |
|---|---|
dataTable | Data Table picker. |
dataFilePath | Data File path picker. |
dataFileFolder | Data File folder picker. |
"properties": {
"tableId": {
"type": "string",
"x-reference": "dataTable",
"description": "Data Table to search"
}
}
How Schema Properties Affect the UI
The same schema drives the input configuration form (when a step uses this input) and the Tool Call step parameter form (when a step calls this tool):
| Schema feature | UI effect |
|---|---|
| Property name | Field label. |
required | Red asterisk after the label. |
description | Helper text under the label. |
x-parameter-locations[name] | A purple chip next to the label showing path, query, header, or body. |
DefaultParameterValues[name] (Configuration Template) | Placeholder text in the field showing the default, plus a tooltip explaining that the default is used when the field is empty. |
default on the property | Same as above. If both exist, DefaultParameterValues wins. |
x-reference | The matching picker component (Data Table / Data File). |
type: "object" or "array" | A two-line text area for JSON. |
| Otherwise | A single-line text box that supports autocomplete and drag-and-drop of step output references. |
The Tool Call step adds two extras: each parameter shows its type as a small chip, and a body parameter that is itself an object opens a structured field-by-field editor with a Raw JSON toggle.
Placeholders
Two placeholder syntaxes are used. They run at different layers, and they do not overlap.
{{ ... }} — Studio Placeholders
These are resolved by Studio before the HTTP request is built. You can use them inside Configuration Template values (headers, body, default parameter values), and inside the input assignment configuration on a step.
| Placeholder | Resolves to |
|---|---|
{{APP_API_KEY}} | The raw API key from the app's credentials. |
{{APP_API_KEY_BASE64}} | The API key Base64-encoded. Useful for Authorization: Basic … headers. |
{{APP_BEARER_TOKEN}} | An OAuth bearer token. For tools, the propagated user access token is used when present; otherwise Studio acquires a Service Principal token from the app credentials. For inputs, Service Principal credentials are always used. |
{{STUDIO_TENANT_ID}} | The Studio tenant ID running the action. |
{{STUDIO_EXECUTION_ID}} | The current run ID. |
{{STUDIO_STEP_ID}} | The current step ID. |
{{SECRET.<NAME>}} | A tenant secret. Names are alphanumeric plus underscore. |
{{VARIABLE.<NAME>}} | A tenant variable. |
{{inputs.<path>}} or {{input.<path>}} | A value from the step's input parameters, including the trigger payload. |
{{steps.<StepName>.<path>}} | An output value from a named earlier step. |
{{<StepName>.<path>}} | Shorthand for the above. |
Sensitive values such as API keys and bearer tokens are masked in the run logs.
{paramName} — OpenAPI Path Parameters
Single braces are the OpenAPI path-parameter syntax. They are filled in from the merged runtime parameters dictionary when the URL is built, so they work in Path, Query, and Body:
"Path": "/api/vendors/{vendorId}",
"Query": { "details": "{includeDetails}" }
Use {vendorId} to refer to a runtime parameter, not {{vendorId}}.
Default Parameter Values
Defaults let you point a parameter at a sensible value without forcing the LLM or the user to supply it. They come from two places:
- The
defaultkeyword inside the schema property. - The
DefaultParameterValuesmap at the root of the Configuration Template.
DefaultParameterValues wins when both exist. Defaults are applied at runtime after the user, the LLM, or the step input supplied their values, but only when the runtime value is missing or empty.
A common pattern: give a path parameter a {{inputs.…}} default that reads from the trigger payload, and write a short description explaining that the LLM can leave the parameter blank.
Tool Descriptions and Why They Matter
For tools, the Description field and the per-parameter description strings in the Parameters Schema are passed to the LLM together with the tool's name and schema. The LLM uses this text to decide:
- Whether the tool is the right one to call.
- What values to put into each parameter.
Write descriptions for the LLM, not for the UI:
- Start with what the tool does and when to use it.
- Mention important constraints such as required formats, allowed enum values, and side effects.
- Be explicit about parameters that have defaults — for example "Leave
vendorIdempty to use the vendor from the current invoice."
Before the schema reaches the LLM, Studio normalises it:
- Every property is marked as required (a constraint of OpenAI's structured output mode). The LLM is therefore asked to provide every property, even ones you marked optional. Use clear descriptions and defaults to handle this gracefully.
additionalProperties: falseis added to every object that does not already specify it.- Unsupported
formatvalues are stripped. Standard ones,description, andenumare kept.
Input descriptions are shown in the editor but are not sent to an LLM, because inputs run deterministically before the Agent step.
Sample Response
The Sample Response is JSON you can paste in to document what a successful response from this input or tool looks like. It is used for:
- Preview during OpenAPI import.
- Documentation in the input or tool editor.
It is not used to drive autocomplete in later steps. Autocomplete for {{StepName.field}} and {{inputs.…}} is built from real outputs of previous runs. To populate autocomplete, run the Action at least once.
Format the sample response as a JSON array of one or more example responses, for example:
[
{ "statusCode": 200, "body": { "vendorId": "V-001", "name": "Northwind" } }
]
Using an OpenAPI Input in a Step
- Open the step.
- Add an input and select the OpenAPI input.
- The step shows the parameter form generated from the Parameters Schema.
- Fill in the parameters or leave them empty to use the configured defaults. Use
{{inputs.…}}or{{StepName.…}}references to chain values from the trigger payload or earlier steps. - Save the step.
At runtime the input runs before the step body, performs the HTTP request, and exposes the parsed response under the input name in the step's input parameters.
Using an OpenAPI Tool
There are two ways to use a tool:
- Agent step — assign the tool to the step. The Agent's LLM sees the tool name, description, and parameter schema, and may call the tool one or more times during reasoning. The Agent supplies parameter values; defaults fill in any blanks.
- Tool Call step — choose the tool and fill in the parameter form yourself. This is useful when the call is deterministic and does not need LLM reasoning.
The Tool Call step uses the same Parameters Schema to render its form, with the same chips, helpers, and pickers as the input configuration view. A body parameter that is an object opens a structured editor; you can switch to a Raw JSON view for cases like passing a whole {{StepName.body}} reference.
Webhook Trigger
Each OpenAPI app can expose a single webhook trigger. When enabled, Studio displays a webhook URL of the form:
{baseUrl}/webhooks/{tenantId}/{appId}
External systems can POST JSON to that URL to start any Action whose trigger is wired to this app's webhook. The payload is delivered to the trigger and is available in the Action's input parameters.
Webhooks are opt-in. New apps have the webhook disabled by default; enable it on the app's General tab when you are ready.
Things to Know
- The two placeholder syntaxes do not overlap.
{{…}}is Studio's template syntax;{paramName}is the OpenAPI path-parameter syntax. Use the right one for the right layer. - Tool schemas are normalised before being sent to the LLM: all properties are made required and
additionalProperties: falseis added. Use defaults and clear descriptions to handle parameters the LLM should usually leave alone. - Sample Response does not power autocomplete in other steps. Run the Action once to populate real autocomplete suggestions from a step output.
- API keys, bearer tokens, and tenant secrets are masked in the run logs.
- Field length limits when editing manually: 8 KB for the Configuration Template, 16 KB for the Tool Call Schema, 32 KB for the Sample Response.
- Importing the same operation twice shows a conflict diff so you can review changes before overwriting an existing input or tool.