Generic REST API Connector Guide
The Generic REST API connector lets Tealfabric workflows integrate with external HTTP services even when no dedicated connector exists. This guide shows how to configure the connector, run common send/receive patterns, and keep request handling reliable in production.
Document information
| Field | Value |
|---|---|
| Canonical URL | /docs/04_connecting-systems/connectors/r/restapi-generic |
| Version (published date) | 2026-06-09 |
| Tags | connectors, reference, restapi-generic |
| Connector ID | restapi-generic-1.1.0 |
When to use this connector
Use this connector when your target system exposes a REST API but does not yet have a dedicated Tealfabric connector. It works well for workflow-driven record creation, status updates, webhook follow-up calls, and synchronization jobs. A consistent request contract for endpoint paths, methods, and response mapping keeps these integrations maintainable as APIs evolve.
Prerequisites
Before creating the integration, confirm the target API base URL, authentication requirements, and expected request/response format. You should also identify which endpoints are safe for automation and which require idempotency controls. Clarifying these details early helps avoid accidental duplicate writes or unexpected side effects.
Describe the API for agents and Trace AI
Generic REST APIs are harder to use than dedicated connectors because each endpoint has its own schema, query parameters, and payload format. Tealfabric cannot infer those details from the connector alone. When you configure an integration, use the description field to point agents at authoritative API documentation—for example an OpenAPI/Swagger URL, a vendor developer portal page, or a stable link to your internal API reference.
Trace AI and other MCP agents read integration metadata through describe_tenant_integration, which includes the integration description. A clear doc link helps the model choose the right endpoints, construct valid payloads, and avoid guessing field names.
Split read and write into separate integrations
Create separate integrations for read and write traffic instead of one integration that mixes both:
| Integration | HTTP methods | Connector operations | Typical use |
|---|---|---|---|
| Read | GET | receive (and test) | List or fetch records, health checks, lookups |
| Write | POST, PUT, PATCH, DELETE | send (and test) | Create, update, or delete records |
Set the default method in connector configuration (or in each workflow call) so the read integration only performs GET requests and the write integration only performs mutating verbs.
Then control agent access with executable_by_ai_agents on each integration:
- Enable it on the read integration when Trace AI should query the API but must not change data.
- Enable it on the write integration only when agents are allowed to create or update records.
- Leave
executable_by_ai_agentsoff on write integrations in environments where chat should stay read-only.
This pattern gives you explicit read-only vs read-write boundaries without sharing one integration that grants both capabilities by default.
Example naming:
Acme CRM — read (GET)— description:https://developers.acme.example/docs/apiAcme CRM — write (POST/PUT/DELETE)— description:https://developers.acme.example/docs/api
See Trace AI Agent for chat usage and agent tooling.
Configuration reference
Connector defaults are stored in the integration configuration and reused during execution. Keep secrets in secure storage and rotate them based on provider policy.
url(required): Base API URL, for examplehttps://api.example.com.api_key(optional): API key sent inX-API-Keyfor APIs that require key-based auth.path(optional): Default base path such as/api/v1.query(optional): Default query parameters.method(optional): Default method used when operation payload does not provide one.timeout_seconds(optional): HTTP request timeout.
Send data to external APIs
The send operation is used for POST, PUT, and PATCH calls. Keep payloads concise, validate required fields before execution, and ensure your workflow can handle transient failures with retries.
const baseUrl = "https://api.example.com/api/v1";
const tenantId = "<TENANT_ID>";
const apiKey = "<API_KEY>";
type SendResponse = {
id?: string;
status?: string;
email?: string;
};
async function createExternalRecord(): Promise<SendResponse> {
const response = await fetch(`${baseUrl}/integrations/<ENTITY_ID>/execute`, {
method: "POST",
headers: {
"X-API-Key": apiKey,
"X-Tenant-ID": tenantId,
"Content-Type": "application/json",
},
body: JSON.stringify({
operation: "send",
method: "POST",
endpoint: "/users",
data: {
name: "Jordan Lee",
email: "jordan.lee@example.com",
status: "active",
},
}),
});
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const payload = (await response.json()) as { success?: boolean; data?: { response?: SendResponse } };
if (!payload.success || !payload.data?.response) throw new Error("Missing API response payload");
return payload.data.response;
}curl -X POST "https://api.example.com/api/v1/integrations/<ENTITY_ID>/execute" \
-H "X-API-Key: <API_KEY>" \
-H "X-Tenant-ID: <TENANT_ID>" \
-H "Content-Type: application/json" \
-d '{
"operation": "send",
"method": "POST",
"endpoint": "/users",
"data": {
"name": "Jordan Lee",
"email": "jordan.lee@example.com",
"status": "active"
}
}'
{
"success": true,
"data": {
"message_count": 1,
"response": {
"id": "<ENTITY_ID>",
"name": "Jordan Lee",
"email": "jordan.lee@example.com",
"status": "active"
},
"http_status": 201
}
}
Retrieve records with filtering
Use the receive operation to fetch one record or a filtered list from an external API. Include pagination and query filters in repeatable workflows to avoid large unbounded responses.
const baseUrl = "https://api.example.com/api/v1";
const tenantId = "<TENANT_ID>";
const apiKey = "<API_KEY>";
type UserRecord = { id: string; name: string; email: string; status: string };
async function listActiveUsers(): Promise<UserRecord[]> {
const response = await fetch(`${baseUrl}/integrations/<ENTITY_ID>/execute`, {
method: "POST",
headers: {
"X-API-Key": apiKey,
"X-Tenant-ID": tenantId,
"Content-Type": "application/json",
},
body: JSON.stringify({
operation: "receive",
endpoint: "/users",
query: {
status: "active",
limit: 20,
offset: 0,
},
}),
});
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const payload = (await response.json()) as { success?: boolean; data?: { data?: UserRecord[] } };
if (!payload.success || !payload.data?.data) throw new Error("Missing records payload");
return payload.data.data;
}Validate connectivity and handle failures
Run the test operation after credential rotation, URL changes, or upstream API version updates. Most production issues come from authentication mismatch, malformed payloads, or unexpected provider-side throttling. Logging HTTP status codes and connector execution identifiers makes incident debugging much faster.
curl -X POST "https://api.example.com/api/v1/integrations/<ENTITY_ID>/execute" \
-H "X-API-Key: <API_KEY>" \
-H "X-Tenant-ID: <TENANT_ID>" \
-H "Content-Type: application/json" \
-d '{
"operation": "test"
}'
{
"success": true,
"data": {
"message": "REST API connection test successful",
"details": {
"base_url": "https://api.example.com",
"api_path": "api/v1",
"http_status": 200,
"response_received": true
}
}
}
test is the only operation that validates required url format and http/https scheme before dispatch. send, receive, and sync rely on runtime HTTP behavior and surface configuration problems through request failures, matching legacy connector execution flow.
Additional references
For broader HTTP design and API behavior patterns, see REST API best practices and MDN HTTP methods. Keeping your workflow request contracts explicit and versioned helps protect integrations from breaking upstream changes.