Workflows API
API reference for workflow execution and management
The Workflows API enables programmatic execution and management of automated AI workflows. Trigger workflows, check run status, and retrieve results.
Base URL
https://www.girardai.com/api/v1
Authentication
All requests require authentication via Bearer token:
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
List Workflows
Get all workflows in your organization.
Endpoint: GET /api/v1/workflows
Query Parameters
| Parameter | Type | Description |
|---|---|---|
limit | number | Max results (default: 20, max: 100) |
offset | number | Pagination offset |
status | string | Filter by status: active, draft, archived |
Example Request
curl -X GET "https://www.girardai.com/api/v1/workflows?limit=10" \
-H "Authorization: Bearer sk_live_xxx"
Response
{
"success": true,
"data": {
"workflows": [
{
"id": "wf_abc123",
"name": "Content Generator",
"description": "Generates blog content from topics",
"status": "active",
"createdAt": "2025-01-10T10:00:00Z",
"updatedAt": "2025-01-15T14:30:00Z"
},
{
"id": "wf_def456",
"name": "Image Pipeline",
"description": "Batch image generation workflow",
"status": "active",
"createdAt": "2025-01-08T09:00:00Z",
"updatedAt": "2025-01-12T11:20:00Z"
}
],
"total": 15,
"limit": 10,
"offset": 0
}
}
Get Workflow
Get details of a specific workflow.
Endpoint: GET /api/v1/workflows/{id}
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Workflow ID |
Example Request
curl -X GET https://www.girardai.com/api/v1/workflows/wf_abc123 \
-H "Authorization: Bearer sk_live_xxx"
Response
{
"success": true,
"data": {
"id": "wf_abc123",
"name": "Content Generator",
"description": "Generates blog content from topics",
"status": "active",
"inputs": [
{
"name": "topic",
"type": "string",
"required": true,
"description": "The blog post topic"
},
{
"name": "tone",
"type": "string",
"required": false,
"default": "professional",
"description": "Writing tone"
}
],
"steps": [
{
"id": "step_1",
"type": "ai_chat",
"name": "Generate Outline"
},
{
"id": "step_2",
"type": "ai_chat",
"name": "Write Content"
}
],
"webhookUrl": "https://www.girardai.com/api/v1/webhooks/wf_abc123",
"createdAt": "2025-01-10T10:00:00Z",
"updatedAt": "2025-01-15T14:30:00Z"
}
}
Execute Workflow
Trigger a workflow execution.
Endpoint: POST /api/v1/workflows/{id}/execute
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Workflow ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
inputs | object | Yes | Input values for the workflow |
async | boolean | No | Run asynchronously (default: true) |
Example Request
curl -X POST https://www.girardai.com/api/v1/workflows/wf_abc123/execute \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"inputs": {
"topic": "The Future of AI in Healthcare",
"tone": "professional"
}
}'
Response (Async)
{
"success": true,
"data": {
"runId": "run_xyz789",
"workflowId": "wf_abc123",
"status": "running",
"message": "Workflow execution started"
}
}
Response (Sync)
When async: false:
{
"success": true,
"data": {
"runId": "run_xyz789",
"workflowId": "wf_abc123",
"status": "completed",
"duration": 15234,
"output": {
"article": "# The Future of AI in Healthcare\n\n..."
}
}
}
Get Run Status
Check the status of a workflow run.
Endpoint: GET /api/v1/runs/{id}
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Run ID |
Example Request
curl -X GET https://www.girardai.com/api/v1/runs/run_xyz789 \
-H "Authorization: Bearer sk_live_xxx"
Response (Running)
{
"success": true,
"data": {
"runId": "run_xyz789",
"workflowId": "wf_abc123",
"status": "running",
"currentStep": "step_2",
"progress": 50,
"startedAt": "2025-01-15T10:30:00Z"
}
}
Response (Completed)
{
"success": true,
"data": {
"runId": "run_xyz789",
"workflowId": "wf_abc123",
"status": "completed",
"duration": 15234,
"startedAt": "2025-01-15T10:30:00Z",
"completedAt": "2025-01-15T10:30:15Z",
"output": {
"article": "# The Future of AI in Healthcare\n\nArtificial intelligence is revolutionizing healthcare..."
},
"stepResults": [
{
"stepId": "step_1",
"name": "Generate Outline",
"status": "completed",
"duration": 3500
},
{
"stepId": "step_2",
"name": "Write Content",
"status": "completed",
"duration": 11734
}
]
}
}
Response (Failed)
{
"success": true,
"data": {
"runId": "run_xyz789",
"workflowId": "wf_abc123",
"status": "failed",
"error": {
"stepId": "step_2",
"message": "AI service temporarily unavailable",
"code": "service_unavailable"
},
"startedAt": "2025-01-15T10:30:00Z",
"failedAt": "2025-01-15T10:30:05Z"
}
}
List Workflow Runs
Get execution history for a workflow.
Endpoint: GET /api/v1/workflows/{id}/runs
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Workflow ID |
Query Parameters
| Parameter | Type | Description |
|---|---|---|
limit | number | Max results (default: 20) |
offset | number | Pagination offset |
status | string | Filter: running, completed, failed |
Example Request
curl -X GET "https://www.girardai.com/api/v1/workflows/wf_abc123/runs?limit=5" \
-H "Authorization: Bearer sk_live_xxx"
Response
{
"success": true,
"data": {
"runs": [
{
"runId": "run_xyz789",
"status": "completed",
"duration": 15234,
"startedAt": "2025-01-15T10:30:00Z"
},
{
"runId": "run_abc456",
"status": "completed",
"duration": 14892,
"startedAt": "2025-01-15T09:15:00Z"
}
],
"total": 42,
"limit": 5,
"offset": 0
}
}
Webhook Trigger
Trigger a workflow via webhook.
Endpoint: POST /api/v1/webhooks/{workflowId}
Headers
| Header | Description |
|---|---|
Content-Type | application/json |
X-Webhook-Secret | Optional secret for verification |
Request Body
Any JSON payload - passed as workflow inputs.
Example Request
curl -X POST https://www.girardai.com/api/v1/webhooks/wf_abc123 \
-H "Content-Type: application/json" \
-H "X-Webhook-Secret: your_secret_here" \
-d '{
"event": "new_order",
"data": {
"orderId": "12345",
"customer": "John Doe"
}
}'
Response
{
"success": true,
"data": {
"runId": "run_webhook_123",
"status": "running"
}
}
Code Examples
JavaScript/TypeScript
class GirardWorkflows {
private apiKey: string;
private baseUrl = 'https://www.girardai.com/api/v1';
constructor(apiKey: string) {
this.apiKey = apiKey;
}
private async request(path: string, options: RequestInit = {}) {
const response = await fetch(`${this.baseUrl}${path}`, {
...options,
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
...options.headers,
},
});
return response.json();
}
async listWorkflows(limit = 20) {
return this.request(`/workflows?limit=${limit}`);
}
async getWorkflow(id: string) {
return this.request(`/workflows/${id}`);
}
async execute(workflowId: string, inputs: Record<string, unknown>) {
return this.request(`/workflows/${workflowId}/execute`, {
method: 'POST',
body: JSON.stringify({ inputs }),
});
}
async getRunStatus(runId: string) {
return this.request(`/runs/${runId}`);
}
async waitForCompletion(runId: string, pollInterval = 2000, timeout = 300000) {
const startTime = Date.now();
while (Date.now() - startTime < timeout) {
const result = await this.getRunStatus(runId);
const status = result.data.status;
if (status === 'completed') {
return result.data;
}
if (status === 'failed') {
throw new Error(result.data.error?.message || 'Workflow failed');
}
await new Promise(resolve => setTimeout(resolve, pollInterval));
}
throw new Error('Workflow execution timeout');
}
async executeAndWait(workflowId: string, inputs: Record<string, unknown>) {
const { data } = await this.execute(workflowId, inputs);
return this.waitForCompletion(data.runId);
}
}
// Usage
const workflows = new GirardWorkflows(process.env.GIRARDAI_API_KEY!);
// Execute and wait for result
const result = await workflows.executeAndWait('wf_abc123', {
topic: 'Machine Learning Basics',
tone: 'educational'
});
console.log('Output:', result.output);
Python
import requests
import time
import os
from typing import Dict, Any, Optional
class GirardWorkflows:
def __init__(self, api_key: Optional[str] = None):
self.api_key = api_key or os.environ.get('GIRARDAI_API_KEY')
self.base_url = 'https://www.girardai.com/api/v1'
def _request(self, method: str, path: str, **kwargs) -> Dict[str, Any]:
headers = {
'Authorization': f'Bearer {self.api_key}',
'Content-Type': 'application/json',
}
response = requests.request(
method,
f'{self.base_url}{path}',
headers=headers,
**kwargs
)
return response.json()
def list_workflows(self, limit: int = 20) -> Dict[str, Any]:
return self._request('GET', f'/workflows?limit={limit}')
def get_workflow(self, workflow_id: str) -> Dict[str, Any]:
return self._request('GET', f'/workflows/{workflow_id}')
def execute(self, workflow_id: str, inputs: Dict[str, Any]) -> Dict[str, Any]:
return self._request(
'POST',
f'/workflows/{workflow_id}/execute',
json={'inputs': inputs}
)
def get_run_status(self, run_id: str) -> Dict[str, Any]:
return self._request('GET', f'/runs/{run_id}')
def wait_for_completion(
self,
run_id: str,
poll_interval: float = 2.0,
timeout: float = 300.0
) -> Dict[str, Any]:
start_time = time.time()
while time.time() - start_time < timeout:
result = self.get_run_status(run_id)
status = result['data']['status']
if status == 'completed':
return result['data']
if status == 'failed':
error = result['data'].get('error', {})
raise Exception(error.get('message', 'Workflow failed'))
time.sleep(poll_interval)
raise Exception('Workflow execution timeout')
def execute_and_wait(
self,
workflow_id: str,
inputs: Dict[str, Any]
) -> Dict[str, Any]:
result = self.execute(workflow_id, inputs)
run_id = result['data']['runId']
return self.wait_for_completion(run_id)
# Usage
workflows = GirardWorkflows()
# Execute and wait
result = workflows.execute_and_wait('wf_abc123', {
'topic': 'Machine Learning Basics',
'tone': 'educational'
})
print('Output:', result['output'])
Webhook Integration
Setting Up Webhooks
- Get your workflow's webhook URL from the workflow details
- Configure your external service to POST to this URL
- Optionally set a webhook secret for verification
Verifying Webhook Signatures
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(`sha256=${expectedSignature}`)
);
}
// In your webhook handler
app.post('/my-webhook', (req, res) => {
const signature = req.headers['x-girardai-signature'];
const isValid = verifyWebhookSignature(
JSON.stringify(req.body),
signature,
process.env.WEBHOOK_SECRET
);
if (!isValid) {
return res.status(401).send('Invalid signature');
}
// Process webhook
});
Error Responses
Error Format
{
"success": false,
"error": {
"code": "error_code",
"message": "Human readable message"
}
}
Error Codes
| Code | Status | Description |
|---|---|---|
unauthorized | 401 | Invalid API key |
not_found | 404 | Workflow/run not found |
validation_error | 400 | Invalid inputs |
workflow_disabled | 400 | Workflow is not active |
rate_limit_exceeded | 429 | Too many requests |
server_error | 500 | Internal error |
Run Status Values
| Status | Description |
|---|---|
queued | Waiting to start |
running | Currently executing |
completed | Finished successfully |
failed | Error occurred |
cancelled | Manually cancelled |
Best Practices
- Use async execution - Don't block on long workflows
- Implement polling - Check status periodically
- Handle failures - Implement retry logic
- Validate inputs - Check inputs before executing
- Monitor runs - Track execution metrics
Previous: Voice API | Next: Creating Agents Guide