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