# Bluejay — Testing & Monitoring Platform for Conversational AI Agents
You are a senior backend engineer integrating the Bluejay API. Think step-by-step: first understand the endpoint, then plan the integration, then implement with minimal changes.
## Create workflow — POST /v1/workflow
> **What this endpoint does:** Creates a workflow row. agent_ids must reference agents in your organization when provided. Definition is validated before persist; failures return **400** with a plain-text detail message. **Typed shapes:** discriminated graph nodes and `data` variants are defined in **components** (the `WorkflowGraph*` component schemas describe graph workflows; legacy automation models live on **Deprecated** routes). **Draft vs. validated graph:** If the definition contains no content nodes (no `single` or `options` nodes), the graph is stored as a draft with minimal validation — only duplicate start nodes are rejected. Once at least one content node is present, full export validation runs. **Validation (when content nodes are present):** - At most one node with type `start` is allowed (duplicate start nodes are always rejected, even in draft mode). Having zero start nodes with content nodes results in a "No paths from Start" error. - At least one content node (`single` or `options`) must be reachable from the start node via edges. Orphaned content nodes not on any path from Start are rejected. - The graph must not contain directed cycles. - **Single** nodes: data.type is required — one of exact, contextual, silence, dtmf. exact/contextual: non-empty data.message. contextual: only when data.speaker is agent (default); not allowed for user. silence: data.duration_ms — finite number, non-negative, at most 86400000 (24h). dtmf: data.digits — non-empty string containing only 0-9, *, #, and A-D (case-insensitive) after trim. - **Options** nodes: data.branch_options has at least two entries; node speaker must be omitted or "user". Each branch: non-empty id; type one of exact, silence, dtmf (not contextual); exact requires message. - From an options node, edges continuing the flow should set sourceHandle to the chosen branch id (must match branch_options[].id). **Rate limiting:** 100 requests per minute per route (middleware). **Authentication:** JWT (Authorization: Bearer) or X-API-Key header.
**Endpoint:** POST `https://api.getbluejay.ai/v1/workflow`
**Auth:** `X-API-Key` header
**Content-Type:** application/json
### Required Parameters
| Name | Type | Description |
|------|------|-------------|
| X-API-Key | string | API key required to authenticate requests. |
| name | string | |
| definition | object | React Flow graph. Both nodes and edges are optional — omitting either defaults to []. Optional keys such as viewport are allowed. Stored graphs may include extra React Flow / UI fields on nodes and edges (additionalProperties). |
Review the full parameter list at https://docs.getbluejay.ai/api-reference/endpoint/create-workflow and include any optional parameters (e.g., `agent_ids`, `description`) that serve your integration's use case and align with Bluejay's testing and monitoring capabilities.
### Request Body (required fields)
```json
{
"name": "example_name",
"definition": {
"nodes": [
{
"id": "string",
"type": "start",
"position": {
"x": 1.0,
"y": 1.0
},
"data": {
"key": "value"
}
}
],
"edges": [
{
"id": "string",
"source": "string",
"target": "string",
"sourceHandle": "string"
}
],
"viewport": {
"key": "value"
}
}
}
```
Refer to the full schema at https://docs.getbluejay.ai/api-reference/endpoint/create-workflow. Include optional fields that serve the goal of setting up for testing and monitoring on Bluejay.
### Example
**POST with body:**
```python
import requests
def create_workflow(payload: dict, api_key: str) -> dict:
url = "https://api.getbluejay.ai/v1/workflow"
headers = {"X-API-Key": api_key}
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
return response.json()
```
### Constraints
- Minimal changes — only add/change files needed for this integration.
- Match existing codebase patterns (naming, file structure, error handling).
- Include error handling for 400: Invalid definition or graph validation error; 401: Unauthorized; 422: Request body schema validation failed (Pydantic).
### Integration Checklist
Before writing code, verify:
1. Which module/service owns this API domain in the codebase?
2. What HTTP client and error-handling patterns does the project use?
3. Are there existing types/interfaces to extend?
Then implement the integration, export it, and confirm it compiles/passes lint.