Skip to content

OpenAPI Integrations ​

Connect Martha to any REST API by importing its OpenAPI specification. Martha extracts endpoints as callable functions, handles authentication, and makes them available to agents and workflows.

Quick Start ​

bash
# Preview what will be imported (dry-run is default)
martha integrations import-openapi \
  --source https://api.example.com/openapi.json \
  --name my-api \
  --prefix myapi_

# Import for real with authentication
martha integrations import-openapi \
  --source https://api.example.com/openapi.json \
  --name my-api \
  --prefix myapi_ \
  --auth-scheme apiKey \
  --auth-header X-Api-Key \
  --auth-value 'your-api-key' \
  --no-dry-run

Authentication ​

Auth is set at import time and applied to all imported functions. Supported schemes:

SchemeHeaderValue format
apiKeyCustom (e.g., X-Api-Key)Raw key value
bearerAuthorizationToken (auto-prefixed with Bearer )
basicAuthorizationuser:pass (auto-encoded to base64)

CLI flags ​

FlagDescription
--auth-schemeapiKey, bearer, basic, oauth2, none
--auth-headerHeader name (default: Authorization)
--auth-valueCredential value
--auth-query-paramFor API keys passed as query parameters
--auth-credential-sourceReference key for credentials stored in your secret store

Credential priority at execution time ​

When a function is called, credentials are resolved in this order:

  1. Session-level (per chat session, highest priority)
  2. Client-level (shared across sessions for a client)
  3. Function definition default (from import-time --auth-value)

Store credentials at the client level for production use:

bash
# Store credential for a client
POST /clients/{client_id}/credentials
{
  "service_name": "my-api",
  "value": "your-api-key",
  "header": "X-Api-Key"
}

How parameters work ​

Martha maps OpenAPI parameters to function parameters:

OpenAPI locationMartha locationAt execution time
in: pathlocation: pathSubstituted into URL template ({param})
in: querylocation: queryAdded to query string
requestBody.properties.*location: bodySent as JSON body fields

For free-form POST bodies (schemas with additionalProperties: true and no properties), any parameter the agent passes that isn't a path or query param is automatically included in the request body.

Post-import setup ​

After importing, grant functions to clients and agents:

bash
# List imported functions
martha functions list --source my-api

# Grant all to a client
martha functions list --limit 200 --json | \
  python3 -c "import json,sys
for f in json.load(sys.stdin):
    if f['name'].startswith('myapi_'): print(f['name'])" | \
  while read name; do
    martha clients grant my-client function "$name"
  done

# Add to an agent
martha agents add-function my-agent myapi_list_items
martha agents add-function my-agent myapi_create_item

Enriching function descriptions ​

Imported functions get their descriptions from the OpenAPI spec's summary field. For better agent behavior, update descriptions with domain context:

bash
martha functions update myapi_create_item -f - <<'EOF'
description: >
  Create an item in the inventory. Pass name (required), category,
  and quantity as parameters. For supplier references, use
  supplier_id=<uuid>. Items are created in "draft" status by default.
EOF

Good descriptions include:

  • What the endpoint does in domain terms
  • Required vs optional parameters
  • Relationship patterns (how to reference related entities)
  • Default behaviors and filters to apply
  • IDs of well-known resources (collections, databases)

Managing specs ​

bash
# List imported specs
martha integrations specs

# Re-sync a spec (picks up new endpoints)
martha integrations sync <spec-id>

# Force re-sync even if hash matches
martha integrations sync <spec-id> --force

Partial specs ​

Not every API publishes an OpenAPI spec. You can write a partial spec covering just the endpoints you need:

yaml
openapi: "3.0.3"
info:
  title: My API (partial)
  version: "1.0"
servers:
  - url: https://api.example.com
security:
  - apiKey: []
components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-Api-Key
paths:
  /api/items:
    get:
      operationId: listItems
      summary: List all items
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
      responses:
        "200":
          description: List of items
    post:
      operationId: createItem
      summary: Create a new item
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [name]
              properties:
                name:
                  type: string
                category:
                  type: string
      responses:
        "201":
          description: Created item

Host it (e.g., as a GitHub gist) and import:

bash
martha integrations import-openapi \
  --source https://gist.githubusercontent.com/.../spec.yaml \
  --name my-api --prefix myapi_ \
  --auth-scheme apiKey --auth-header X-Api-Key \
  --auth-value 'key' --no-dry-run

Troubleshooting ​

"Entity type not found" or "Unknown field" on POST ​

The function handler may be sending path parameters in the request body. Check:

bash
martha functions get myapi_create_item --json | python3 -c "
import json, sys
params = json.load(sys.stdin).get('definition',{}).get('parameters',{})
for k, v in params.items():
    print(f'{k}: location={v.get(\"location\")}')"

Path parameters should show location=path. If they show location=None, the spec was imported with an older version of the import service -- reimport.

Functions not showing body parameters ​

If a POST endpoint's body fields don't appear in the function parameters, the requestBody schema may use $ref that didn't resolve, or the schema has additionalProperties: true with no properties. In the latter case, this is expected -- the agent can pass any field and it will be routed to the body automatically.

Auth errors (401/403) ​

Check the stored auth config:

bash
martha functions get myapi_list_items --json | python3 -c "
import json, sys
auth = json.load(sys.stdin).get('definition',{}).get('auth',{})
print(json.dumps(auth, indent=2))"

If value contains ${VAR}, the variable must exist as an environment variable in the running deployment. For reliability, use a literal credential value or set the credential at the connection level so it's resolved from the secret store at call time.

Martha is built by aiaiai-pt.