Connect a REST API
Connect a REST API to my agent
Connect a vendor’s REST API to my Speechify agent as an OpenAPI tool: store the vendor’s OAuth client credentials in the vault, import its OpenAPI document, choose the read operations the agent needs and classify them, add response mappings that keep only the fields it needs, preview one call, then create the tool and attach it to my agent.
Follow [https://docs.speechify.ai/agents/guides/connect-a-rest-api.md](https://docs.speechify.ai/agents/guides/connect-a-rest-api.md).Agents is in beta. Shapes on /v1/agents/* and /v1/credentials may change before general availability.
An openapi tool gives an agent a vendor’s REST API from the vendor’s own OpenAPI document.
You pick the operations the agent may call, say what each one does to the world, and trim what comes back; Speechify’s servers make every call with a credential from your vault.
There is no connector to write or host.
When to use it
What the platform handles for you: the OAuth token and its renewal, a per-minute ceiling you set once and every agent, run and route shares, a vendor 429 reported to the agent as a wait rather than a failure, and a result trimmed to the fields you chose.
What it will not do is transform results with logic: there are no filters, conditionals or arithmetic, and anything richer belongs in your own connector.
1. Store the vendor credential
For a vendor that issues OAuth client credentials, create a credential of kind oauth2_client_credentials:
token_endpoint_auth_methodis how the platform authenticates totoken_url:client_secret_post(the default) sends the id and secret in the form body, andclient_secret_basicsends them in an HTTP Basic header. Use whichever the vendor’s documentation names.scopesare sent space-separated asscope, andaudience, when set, is sent asaudience.- A vendor that issues a static API token instead takes a credential of kind
bearer, sent asAuthorization: Bearer <token>.
Keep the credential’s id.
The secret is never returned again: every read shows client_secret_set: true instead.
A credential with no project_id can back tools in every project; one scoped to a project can only back tools in that project.
2. Import the document
Pass the document’s URL, and the credential when the vendor serves its document behind the same auth as its API:
Or paste the document inline as spec, a JSON object or a string holding JSON or YAML, up to 2 MiB.
Nothing is saved.
Read the answer in this order:
error: set when nothing compiled, with the reason (a refused URL, a credential that did not resolve, a fetch that failed, a document that does not parse). The call still answers200.operations: every operation that compiled, in document order, each already in the shape the tool takes.skipped: every operation that could not be represented, with the reason, such as a request body that is not JSON.base_url: the document’s first https server. Use the vendor’s regional or tenant host instead when your account has one.
3. Choose and classify operations
Copy the operations the agent should have into the tool’s operations, at most 40 per tool.
Fewer is better: a model picks more reliably from a dozen well-described functions than from a catalogue.
Keep each operation’s id as the import returned it, or rename it before saving; do not derive ids yourself, since the import collapses and suffixes them in ways the document does not show.
The agent calls each operation as the function <tool name>__<operation id>, which must fit 64 characters.
Shorten the tool name, or rename an operation’s id, when a pair does not fit.
Give every operation an action_class.
It decides what runs without a person:
An operation that declares nothing is read when it is a GET or HEAD, and otherwise takes the tool’s own action_class, which is irreversible_other when the tool declares none.
Only a read operation can be previewed in step 5, and only a read operation on a tool whose approval is null or auto can be served from a hosted API route.
A live voice or text session cannot pause for approval, so an operation that needs one is refused there and the agent is told it can run from a durable run.
The document’s security schemes are not imported: the tool authenticates with its own auth.
If the document lists an API key as a header or query parameter, do not keep that parameter, because the agent would have to supply the key’s value.
Only bearer and oauth2_client_credentials auth are supported.
4. Shape what the agent reads
A vendor’s answer is often far larger than what the agent needs, and the agent reads only a bounded window of it.
Add a response mapping to an operation to decide which fields survive:
The three steps apply in this order:
max_itemskeeps the first N elements of a root array, or of every top-level array of a root object.pickkeeps only the named paths, up to 50.issues[].idkeepsissuesas an array whose objects hold onlyid;[].idaddresses a root array.deriveadds string fields, up to 20. The key is where the field lands, and{{path}}placeholders in the value resolve relative to that scope, so the example gives every issue its ownurl.
A path the answer does not have leaves nothing, and a placeholder with no value renders empty, both silently. That is why the next step exists.
5. Preview one call
Send the whole config you are about to save, the operation’s id, and the arguments the agent would pass:
The call really reaches the vendor, so it counts against the vendor’s own limits, but it never saves anything and runs read operations only.
It needs the content.manage permission, like creating a tool.
Read the result in this order:
erroris set only when no call was made: a config the create endpoint would refuse, an operation the config does not have, a write operation, or a credential that does not resolve.outcomesays how the call ended. Onlyokis a preview that worked.- On
ok, compareraw(the vendor’s answer) withmapped(the same answer after your mapping).observationis exactly what the agent reads.
applied is also true when every pick path missed and the answer became empty, so read mapped rather than trusting applied.
6. Create the tool
base_urlis https only and wins over the document’s servers.- Keep
spec_urlso a later import can refresh the operations. max_requests_per_minuteis one budget shared by every agent, run and hosted API route that calls this tool. Set it below the vendor’s own limit, so an agent never spends the allowance your team’s other integrations need.timeout_msbounds one call, 30000 by default.
To change the tool later, send the full config to PATCH /v1/agents/tool-definitions/{tool_definition_id}: it replaces the stored config whole.
7. Give it to an agent
Attach the tool to an agent:
Or name it in a skill’s tool_ids with POST /v1/skills, and every agent that attaches the skill gets the tool’s operations.
The tool works on every surface an agent runs on: a voice call, a text conversation and a durable run. Its calls are made by Speechify’s servers on all of them, so the vendor credential never leaves the vault for a call.
Refresh when the vendor changes
The tool stores the operations you chose, never the document, so a vendor renaming or reshaping its API cannot change an agent’s functions on its own.
To pick up the vendor’s changes, import the same spec_url again, compare the answer with the tool’s operations, and send the updated config.
Limits
Errors
Next
- Serve the tool’s read operations to your own MCP client or to other applications: Serve tools over MCP.
- The other tool kinds: Add tools.