# Flow Execution

Execute flows programmatically and retrieve results.

## Run a flow

```
POST /api/v1/flows/{flowId}/runs
```

The `flowId` can be either the flow's **slug name** (e.g. `product_description`) or its **ObjectId**.

### Request body

| Field               | Type         | Required | Description                                                                  |
| ------------------- | ------------ | -------- | ---------------------------------------------------------------------------- |
| `parameters`        | object       | no       | Key-value map of template parameters. Keys must match `[[param]]` tokens.    |
| `environment`       | string       | no       | Environment name (e.g. `"production"`). Determines which version runs.       |
| `messages`          | array        | no       | Additional chat messages appended after the template's system/user messages. |
| `entrypoint`        | string       | no       | Override which template to use as entrypoint (by name).                      |
| `version`           | string       | no       | Override which version to use (by ID). Takes precedence over environment.    |
| `overrideModel`     | string       | no       | Force a specific model, bypassing template and routing config.               |
| `temperature`       | float        | no       | Override temperature.                                                        |
| `maxTokens`         | integer      | no       | Override max output tokens.                                                  |
| `maxThinkingTokens` | integer      | no       | Budget for extended thinking (reasoning models).                             |
| `maxToolCalls`      | integer      | no       | Max tool-calling loop iterations.                                            |
| `responseSchema`    | object       | no       | JSON Schema for structured output. Overrides template's schema.              |
| `vendorTools`       | string array | no       | Provider-native tools to enable (e.g. `["web_search"]`).                     |
| `tags`              | string array | no       | Tags for filtering in invocation log and statistics.                         |
| `nonce`             | string       | no       | Cache-bust string. Affects response cache hash, never sent to LLM.           |
| `logLevel`          | string       | no       | Override logging level: `Trace`, `Debug`, `Information`, `Warning`, `Error`. |
| `customerId`        | string       | no       | End-customer ID for per-customer usage tracking.                             |

### Headers

| Header                  | Description                                                  |
| ----------------------- | ------------------------------------------------------------ |
| `Authorization`         | `Bearer YOUR_API_KEY` (required)                             |
| `X-Shuttle-Customer-Id` | End-customer ID (takes precedence over `customerId` in body) |
| `X-Shuttle-Debug-Url`   | Attach a debug URL tag for tracing                           |

### Example

```bash
curl -X POST https://app.promptshuttle.com/api/v1/flows/product_description/runs \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "parameters": {
      "product_name": "Smart Water Bottle",
      "tone": "playful"
    },
    "environment": "production",
    "tags": ["campaign-spring-2025"]
  }'
```

### Response

```json
{
  "id": "67a1b2c3d4e5f6a7b8c9d0e1",
  "timestamp": "2025-03-15T10:30:00Z",
  "flowId": "67a1b2c3d4e5f6a7b8c9d0e2",
  "tenantId": "67a1b2c3d4e5f6a7b8c9d0e3",
  "creditsUsed": 1250,
  "milliseconds": 1832,
  "usage": {
    "creditsUsed": 1250,
    "creditsLeft": 998750,
    "tokensIn": 85,
    "tokensOut": 142,
    "reasoningTokens": 0,
    "toolCost": 0,
    "costUsd": 0.00125
  },
  "flowRequest": {
    "parameters": {
      "product_name": "Smart Water Bottle",
      "tone": "playful"
    },
    "environment": "production",
    "tags": ["campaign-spring-2025"]
  },
  "responses": [
    {
      "model": "gpt-4o",
      "provider": "openai",
      "textResponse": "Meet the Smart Water Bottle — your hydration sidekick that...",
      "status": "completed",
      "finishReason": "stop",
      "usage": {
        "tokensIn": 85,
        "tokensOut": 142,
        "costUsd": 0.00125
      }
    }
  ],
  "warnings": []
}
```

### Response fields

| Field                      | Type         | Description                                              |
| -------------------------- | ------------ | -------------------------------------------------------- |
| `id`                       | string       | Unique run ID. Use this for feedback, agent trees, etc.  |
| `timestamp`                | datetime     | When the run was created.                                |
| `creditsUsed`              | long         | Total credits consumed (1M credits = $1).                |
| `milliseconds`             | integer      | Total execution time.                                    |
| `usage`                    | object       | Detailed usage breakdown.                                |
| `usage.creditsLeft`        | long         | Remaining tenant credit balance.                         |
| `responses`                | array        | Inference responses (one per LLM call in the chain).     |
| `responses[].textResponse` | string       | The LLM's text output.                                   |
| `responses[].toolCalls`    | array        | Any tool calls returned (if tool loop hasn't completed). |
| `responses[].citations`    | array        | Citation URLs (Perplexity only).                         |
| `warnings`                 | string array | Warnings about unused/unresolved parameters.             |

## Discover parameters

Before running a flow, you can check what parameters it expects:

```
GET /api/v1/flows/{flowId}/parameters
```

**Query parameters:**

| Param         | Description                                   |
| ------------- | --------------------------------------------- |
| `environment` | Environment to resolve the active version for |
| `version`     | Specific version ID                           |
| `entrypoint`  | Specific template name                        |

**Response:**

```json
[
  { "token": "product_name", "source": "template" },
  { "token": "tone", "source": "template" }
]
```

## Submit feedback

Collect feedback on run quality for monitoring and fine-tuning:

```
POST /api/v1/feedback
```

```json
{
  "shuttleRequestId": "67a1b2c3d4e5f6a7b8c9d0e1",
  "score": 1,
  "text": "Great response, very accurate",
  "endUserId": "user_123"
}
```

| Field              | Type    | Required | Description                                |
| ------------------ | ------- | -------- | ------------------------------------------ |
| `shuttleRequestId` | string  | yes      | The run ID to attach feedback to           |
| `score`            | integer | yes      | Must be `+1` (positive) or `-1` (negative) |
| `text`             | string  | no       | Free-text feedback                         |
| `endUserId`        | string  | no       | Your end-user's identifier                 |

Feedback is upserted: submitting again for the same request replaces the previous feedback.

## Get agent execution tree

For flows that use agent tools (multi-agent orchestration), retrieve the full execution hierarchy:

```
GET /api/v1/flows/{flowId}/runs/{runId}/agent-tree
```

Returns a tree structure showing:

* Each agent invocation with its role, duration, and cost
* Tool calls made by each agent
* Child agents spawned
* Cumulative vs. direct credit usage
* Status and error messages

```json
{
  "requestId": "root_request_id",
  "agentRole": "main",
  "depth": 0,
  "durationMs": 5420,
  "creditsUsed": 3500,
  "totalTreeCreditsUsed": 8200,
  "toolCalls": [
    {
      "toolName": "research_agent",
      "toolType": "Agent",
      "durationMs": 2100,
      "spawnedRequestId": "child_request_id"
    }
  ],
  "children": [
    {
      "requestId": "child_request_id",
      "agentRole": "research_agent",
      "depth": 1,
      "creditsUsed": 4700,
      "children": []
    }
  ]
}
```
