- 🖥️ UI - Affects StackOne Hub, Dashboard, or Connect flows
- 🤖 MCP - Used in MCP tool declarations (
list tools) - ⚙️ Runtime - Affects API request execution
File Structure
Connectors use a modular file structure:Why use partial files?
Why use partial files?
stackone push. The $ref syntax tells the merger which partials to include. File naming must follow the pattern {provider}.{resource}.s1.partial.yaml for auto-discovery.Example from BambooHR:bamboohr.connector.s1.yaml- Auth configbamboohr.employees.s1.partial.yaml- Employee actionsbamboohr.timeoff.s1.partial.yaml- Time-off actions
Root Properties
StackOne
Impact: ⚙️ Runtime
The schema version for the connector file format.
| Value | Description |
|---|---|
1.0.0 | Current and only supported version |
How version affects processing
How version affects processing
1.0.0 is supported. Future versions may introduce new properties or change behavior. Always use 1.0.0 for new connectors.info Section
Metadata about the connector displayed in the UI and used for identification.
info.title
Impact: 🖥️ UI
Human-readable provider name displayed in the Hub and Dashboard.
UI display locations
UI display locations
- Integration Hub provider list
- Dashboard connector cards
- Account connection screens
- Logs and audit trails
info.key
Impact: 🖥️ UI | 🤖 MCP | ⚙️ Runtime
Unique identifier for the connector. Used in API calls, MCP tool names, and internal routing.
| Constraint | Description |
|---|---|
| Format | Lowercase alphanumeric with underscores |
| Uniqueness | Must be unique across all connectors |
| Stability | Cannot change once deployed (breaks linked accounts) |
How key is used throughout the system
How key is used throughout the system
bamboohr_list_employeesAPI: Used in account connections:info.version
Impact: 🖥️ UI | ⚙️ Runtime
Connector version following semver format.
Version management best practices
Version management best practices
- Major (1.x.x): Breaking changes to actions or auth
- Minor (x.1.x): New actions or optional parameters
- Patch (x.x.1): Bug fixes, description updates
info.assets.icon
Impact: 🖥️ UI
URL to the provider’s logo image. Displayed throughout the UI.
Logo requirements and hosting
Logo requirements and hosting
https://stackone-logos.com/api/{provider}/filled/pngRequirements:- 24x24 pixels minimum
- PNG or SVG format
- Transparent background preferred
- Hosted on HTTPS
info.description
Impact: 🖥️ UI | 🤖 MCP
Brief description of the connector’s purpose.
Where description appears
Where description appears
- Keep under 200 characters
- Mention key capabilities
- Include category context (HRIS, CRM, etc.)
baseUrl
Impact: ⚙️ Runtime
The root URL for all API requests. Supports static URLs and dynamic interpolation.
Static URL
Dynamic URL with credentials
Dynamic URL with config
URL interpolation and runtime resolution
URL interpolation and runtime resolution
${...} string interpolation:Available contexts:${credentials.*}- Values from setupFields/configFields${config.*}- Configuration values${env.*}- Environment variables (limited)
acme-corp, the runtime resolves to:rateLimit
Impact: ⚙️ Runtime
Configure rate limiting to respect provider API limits.
| Property | Type | Description |
|---|---|---|
mainRatelimit | number | Max requests per second |
Rate limiting behavior
Rate limiting behavior
- Set slightly below provider’s documented limit
- Check provider API docs for per-endpoint limits
- Some providers have different limits for different endpoints
resources
Impact: 🖥️ UI
URL to the provider’s API documentation. Displayed as a help link in the UI.
Resource link usage
Resource link usage
- Connector configuration screens
- Troubleshooting guides
- Developer documentation references
authentication Section
Defines how end-users authenticate with the provider. Supports multiple auth methods per connector.
Authentication Array Structure
Multiple auth methods
Multiple auth methods
- Users see all options in the Hub during connection
- Each method has independent credentials and setup flows
- Linked accounts store which method was used
- Runtime uses the appropriate auth handler based on account config
- OAuth 2.0
- Custom Auth (API Key, Basic)
OAuth 2.0 Authentication
Impact: 🖥️ UI | ⚙️ Runtimetype
| Value | Description |
|---|---|
oauth2 | OAuth 2.0 authorization code flow |
custom | API Key, Basic Auth, or other non-OAuth |
label
Impact: 🖥️ UIDisplay name for this auth method in the Hub.support
Impact: 🖥️ UIHelp text and links shown during connection flow.Support section display
Support section display
descriptionappears as instructional textlinkcreates a “Learn more” button
authorization
Impact: ⚙️ RuntimeOAuth flow configuration.| Property | Type | Description |
|---|---|---|
authorizationUrl | string | Provider’s OAuth authorize endpoint |
authorizationParams | object | Query params for authorization request |
tokenUrl | string | Provider’s token exchange endpoint |
token | JSONPath | Path to access token in credentials |
includeBearer | boolean | Add “Bearer ” prefix to Authorization header |
pkce | boolean | Enable PKCE (Proof Key for Code Exchange) |
OAuth flow internals
OAuth flow internals
- User clicks “Connect” in Hub
- Runtime builds authorization URL with
authorizationParams - User redirects to provider, logs in, grants permissions
- Provider redirects back with authorization code
- Runtime exchanges code for tokens via
tokenUrl - Tokens stored in credentials for linked account
$.credentials.*- JSONPath to credential values${apiHostUri}- StackOne callback URL base'{{expression ?? default}}'- JEXL with fallback
code_verifier and code_challenge automatically.Scopes: The example '{{$.credentials.scopes ?? "default:scope"}}' lets users customize scopes in setupFields while providing sensible defaults.setupFields
Impact: 🖥️ UI | ⚙️ RuntimeFields collected when configuring the connector (T1 - your app’s credentials).| Property | Type | Description |
|---|---|---|
key | string | Credential storage key (referenced as $.credentials.{key}) |
label | string | 🖥️ Field label in UI |
type | enum | text, password, url |
required | boolean | Field must have a value |
secret | boolean | Encrypt at rest, mask in UI |
placeholder | string | 🖥️ Example value shown in empty field |
description | string | 🖥️ Help text below field |
tooltip | string | 🖥️ Hover/info icon text |
setupFields vs configFields
setupFields vs configFields
- OAuth Client ID/Secret
- API keys for your platform
- Application-level settings
- Their API keys
- Account-specific settings (subdomain, region)
- Personal access tokens
- setupFields → Stored per auth configuration
- configFields → Stored per linked account
secret: true→ Encrypted at rest, never exposed in API responsestype: password→ Masked in UI during entry
configFields
Impact: 🖥️ UI | ⚙️ RuntimeFields collected from end-users during connection (T2 - their credentials).setupFields.refreshAuthentication
Impact: ⚙️ RuntimeEmbedded action for refreshing expired OAuth tokens.Token refresh mechanics
Token refresh mechanics
- An action fails with 401 Unauthorized
- Runtime checks if refreshAuthentication is configured
- Executes the embedded refresh action
- Updates stored credentials with new tokens
- Retries the original action
- Call the provider’s token refresh endpoint
- Map the response to credential format (accessToken, refreshToken, expiresIn)
- Return data in
result.data
categories: [internal] hides this from MCP tool listings.environments
Impact: 🖥️ UIAvailable deployment environments for this auth method.Multi-environment support
Multi-environment support
$.environment.key.testActions
Impact: 🖥️ UI | ⚙️ RuntimeActions executed to validate a connection after OAuth completes.| Property | Type | Description |
|---|---|---|
action | string | Action ID to execute |
required | boolean | Connection fails if action fails |
Connection validation flow
Connection validation flow
- Runtime executes each testAction in order
- If
required: trueand action fails → connection marked as failed - If
required: falseand action fails → warning logged but connection succeeds
- Use a simple read action (list, get)
- Test the most common use case
- Avoid actions that modify data
actions Section
Actions define the operations available through the connector. Use $ref to include partials.
Action References
How $ref resolution works
How $ref resolution works
$ref at build time:$ref: bamboohr.employeeslooks forbamboohr.employees.s1.partial.yaml- Partial file must be in same directory as main connector
- Actions from partial are merged into main connector
- Multiple
$refstatements combine all partials
- (array items), not actions:.Action Properties
Each action defines a single operation.actionId
Impact: 🤖 MCP | ⚙️ Runtime
Unique identifier for the action. Becomes the MCP tool name with provider prefix.
bamboohr_list_employees
| Constraint | Description |
|---|---|
| Format | snake_case, lowercase |
| Uniqueness | Must be unique within connector |
| Convention | {verb}_{resource} or {verb}_{resource}_{variant} |
Action ID naming conventions
Action ID naming conventions
list_*- Get multiple records (paginated)get_*- Get single record by IDcreate_*- Create new recordupdate_*- Modify existing recorddelete_*- Remove recordsearch_*- Query with filters
list_employees- List all employeesget_employee- Get employee by IDcreate_employee- Create new employeesearch_employees_by_department- Filtered search
{provider_key}_{actionId}, so bamboohr + list_employees = bamboohr_list_employees.categories
Impact: 🖥️ UI
Categories for filtering in the UI. Does not affect MCP.
| Category | Description |
|---|---|
hris | HR Information Systems |
ats | Applicant Tracking Systems |
crm | Customer Relationship Management |
lms | Learning Management Systems |
marketing | Marketing automation |
filestorage | File storage and documents |
ticketing | Support ticketing |
messaging | Chat and messaging |
internal | Hidden from UI (used for refresh tokens) |
Category filtering behavior
Category filtering behavior
- Actions Explorer in Dashboard
- AI Playground action selection
- SDK
fetchTools({ categories: ['hris'] })
internal category: Actions with categories: [internal] are:- Hidden from UI listings
- Not returned in MCP
list tools - Still executable via direct API calls
- Used for token refresh and internal operations
actionType
Impact: 🤖 MCP | ⚙️ Runtime
Determines the action’s behavior pattern and response schema.
| Type | Description | Response Schema |
|---|---|---|
custom | Provider-specific action | Raw provider response |
list | Paginated list (unified) | { data: [], next: string } |
get | Single record (unified) | { data: object } |
create | Create record (unified) | { data: object } |
update | Update record (unified) | { data: object } |
delete | Delete record (unified) | { success: boolean } |
refresh_token | Token refresh (internal) | Credential object |
Unified vs Custom action types
Unified vs Custom action types
- Enforce consistent response schemas across providers
- Enable cross-provider compatibility
- Support automatic pagination handling
- Normalize error responses
- Returns raw provider response
- Use for provider-specific features
- No schema normalization
- Full flexibility for unique endpoints
list action always returns:custom action returns whatever the provider returns.label
Impact: 🖥️ UI
Human-readable name displayed in the UI.
Label display locations
Label display locations
- Actions Explorer
- AI Playground action selector
- Request logs
- Error messages
- Use title case
- Start with verb (List, Get, Create, etc.)
- Keep concise (under 30 characters)
description
Impact: 🖥️ UI | 🤖 MCP
Short description of what the action does. Used in both UI and MCP tool descriptions.
Description in MCP tool declarations
Description in MCP tool declarations
list tools, the description becomes the tool’s description:- Understand the action’s purpose
- Know what data it returns
- Decide which action fits the user’s request
- Keep under 200 characters
- Mention key capabilities
- Be specific about what’s returned
details
Impact: 🤖 MCP
Extended description with full context. Used as the complete tool description in MCP.
Details vs Description in MCP
Details vs Description in MCP
descriptionas a brief summarydetailsas the full tool description
description: One-line summary (~100 chars)details: Full context for AI agents (~500 chars)
- What fields are returned
- How pagination works
- What filters are available
- Edge cases and limitations
resources
Impact: 🖥️ UI
Link to provider documentation for this specific action.
Action-level resources
Action-level resources
inputs
Impact: 🤖 MCP | ⚙️ Runtime
Define parameters the action accepts. Become MCP tool input schema.
Input Properties
| Property | Type | Description |
|---|---|---|
name | string | Parameter name (used in expressions as $.inputs.{name}) |
type | enum | Data type (see below) |
description | string | 🤖 MCP - Shown in tool schema |
required | boolean | Whether parameter is mandatory |
default | any | Default value if not provided |
in | enum | Where to send: path, query, body, header |
array | boolean | Parameter accepts array of values |
properties | array | Nested properties for type: object (see accordion below) |
Input Types
| Type | Description | Example |
|---|---|---|
string | Text value | "john@example.com" |
number | Numeric value | 42, 3.14 |
boolean | True/false | true, false |
datetime_string | ISO 8601 date/time | "2024-01-15T10:30:00Z" |
object | JSON object | { "key": "value" } |
enum | Predefined options | See below |
Enum Type
MCP input schema generation
MCP input schema generation
- Generate valid tool calls
- Understand parameter types
- Apply default values
- Validate inputs before calling
Array inputs
Array inputs
array: true for parameters accepting multiple values:"type": "array", "items": { "type": "string" }Object type with nested properties
Object type with nested properties
type: object with a nested properties array to define the object’s structure:properties supports the same fields as top-level inputs (name, type, description, required, default, properties for deeper nesting).This generates proper JSON Schema for MCP, helping AI agents understand the expected object structure:steps
Impact: ⚙️ Runtime
Define the execution flow for the action. Steps run sequentially.
Step Properties
| Property | Type | Description |
|---|---|---|
stepId | string | Unique identifier within action |
description | string | What this step does (for debugging) |
condition | JEXL | Skip step if condition is false |
ignoreError | boolean | Continue execution if this step fails (default: false) |
stepFunction | object | Function to execute (for simple steps) |
iterator | JSONPath | Array expression — makes this a foreach step. See Iterator Steps |
stepFunctions | array | Multiple functions to execute per iteration (use with iterator) |
Conditional Steps
Condition expressions
Condition expressions
| Function | Description | Example |
|---|---|---|
present(x) | Value exists and not null | present(inputs.filter) |
blank(x) | Value is null, undefined, or empty | blank(inputs.cursor) |
Step Functions
request
Impact: ⚙️ Runtime
Make an HTTP request to the provider API.
| Parameter | Type | Description |
|---|---|---|
baseUrl | string | Override connector baseUrl |
url | string | Endpoint path (appended to baseUrl) |
method | enum | get, post, put, patch, delete |
authorization | object | Override connector auth |
args | array | Request parameters |
response.collection | boolean | Whether response is an array (default: true) |
response.dataKey | string | Extract data from this key in response |
response.indexField | string | Field to use as index for keyed results |
customErrors | array | Remap provider error responses (see below) |
Args Location (in)
| Value | Description |
|---|---|
path | URL path parameter: /employees/{id} |
query | Query string: ?field=value |
body | Request body (JSON) |
headers | HTTP header |
Request construction internals
Request construction internals
- URL:
baseUrl+urlwith path params interpolated - Query: All
in: queryargs joined with& - Body: All
in: bodyargs merged into JSON object - Headers: Connector auth headers + custom headers +
in: headersargs
/employees/123/time-off/456Body construction:{ "firstName": "John", "lastName": "Doe" }Custom error handling
Custom error handling
customErrors to remap provider error responses. This is useful for:- GraphQL APIs that return errors with 200 status codes
- Provider-specific error formats that need normalization
- Custom error messages for better AI agent understanding
| Property | Type | Description |
|---|---|---|
receivedStatus | number | HTTP status to match from provider |
targetStatus | number | HTTP status to return instead |
condition | string | JEXL expression (only trigger error if true) |
message | string | Custom error message |
condition property is useful for GraphQL APIs where errors are returned in the response body with a 200 status code.paginated_request
Impact: ⚙️ Runtime
Automatically handle pagination for list endpoints.
Pagination Types
Pagination handling mechanics
Pagination handling mechanics
- Make initial request without cursor
- Read
cursor_pathfrom response - If cursor exists, make next request with cursor in
cursor_position - Repeat until no cursor returned
- Aggregate all
data_pathresults
next cursor allows fetching subsequent pages by passing it back as an input parameter.map_fields
Impact: ⚙️ Runtime
Transform data between formats.
| Parameter | Type | Description |
|---|---|---|
fields | array | Mapping definitions |
dataSource | JSONPath | Source data to transform |
fields[].targetFieldKey | string | Output field name |
fields[].expression | JEXL | Value expression |
fields[].type | enum | Output type |
Field mapping expressions
Field mapping expressions
type field ensures output matches expected type:string- Converts to stringnumber- Converts to numberboolean- Converts to booleandatetime_string- Formats as ISO 8601
group_data
Impact: ⚙️ Runtime
Group array data by a field.
Group data usage
Group data usage
typecast
Impact: ⚙️ Runtime
Convert data types.
| Type | Description |
|---|---|
string | Convert to string |
number | Parse as number |
boolean | Convert to boolean |
json | Parse JSON string to object |
soap_request
Impact: ⚙️ Runtime
Make SOAP API requests. Used primarily for enterprise providers like Workday.
| Parameter | Type | Description |
|---|---|---|
baseUrl | string | SOAP service base URL |
url | string | SOAP endpoint path |
method | enum | HTTP method (typically post) |
authorization | object | Auth config (same as request) |
soapOperation | string | SOAP operation name |
useSoapContext | boolean | Use SOAP context (default: false) |
namespaces | array | XML namespace definitions |
args | array | Request parameters |
SOAP namespace configuration
SOAP namespace configuration
@_ prefix for XML attributes and #text for text content.static_values
Impact: ⚙️ Runtime
Return predefined static values without making an API request. Useful for enum lookups or constant data.
| Parameter | Type | Description |
|---|---|---|
values | array | Array of static objects to return |
Static values use cases
Static values use cases
static_values when:- Provider doesn’t have an API endpoint for enum values:
- Combining with dynamic data via multi-step actions:
merge_collections
Impact: ⚙️ Runtime
Merge multiple data collections into a single array.
| Parameter | Type | Description |
|---|---|---|
collections | array | JSONPath references to arrays to merge |
Merge collections example
Merge collections example
Iterator Steps
Impact: ⚙️ Runtime Iterator steps (foreach) execute step function(s) for each item in an array. Define by adding theiterator property to a step.
| Property | Type | Description |
|---|---|---|
iterator | JSONPath | Expression that evaluates to an array |
stepFunction | object | Single function to execute per item |
stepFunctions | array | Multiple functions to execute per item (mutually exclusive with stepFunction) |
Iterator context variables
Iterator context variables
| Variable | Description |
|---|---|
$.iterator.item | Current array element |
$.iterator.index | Current iteration index (0-based) |
$.iterator.current | Output from previous step function in stepFunctions sequence |
${iterator.item} | String interpolation of current item (for URLs) |
$.steps.{stepId}.output.data as an array.result
Impact: 🤖 MCP | ⚙️ Runtime
Define the action’s output. Becomes the tool’s return value.
| Property | Description |
|---|---|
data | Primary response data (returned to caller) |
rawRequest | Original HTTP request (for debugging) |
rawResponse | Original HTTP response (for debugging) |
Result in MCP responses
Result in MCP responses
Expression Formats
Three expression formats are available throughout connector YAML. For the complete reference including all built-in functions, see the Expression Language page.JSONPath ($.path)
Access data from context objects.
| Context | Description |
|---|---|
$.credentials | Auth credentials |
$.inputs | Action input parameters |
$.config | Connector configuration |
$.steps.{stepId}.output | Previous step output |
String Interpolation (${...})
Embed values in strings.
JEXL ('{{...}}')
Complex expressions with logic.
Expression format selection guide
Expression format selection guide
- Simple value access
- No transformation needed
- Used alone (not in string)
- Building URLs or strings
- Concatenating with static text
- Simple variable substitution
- Default values needed (
??operator) - Conditional logic required
- Complex transformations
- In
conditionfields
GraphQL Actions
For GraphQL APIs, use therequest function with POST method and query in body.
GraphQL best practices
GraphQL best practices
- Define variables for all dynamic values
- Use fragments for reusable field selections
- Keep queries focused (request only needed fields)
errors field in response:variables object, not inline in query: