> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pictory.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Windsurf Setup for Pictory API

> Configure Windsurf's Cascade to call the Pictory API with workspace rules, MCP integration, and proven prompts

[Windsurf](https://windsurf.com) is an agentic IDE powered by Cascade. This page shows you how to configure it for productive work against the Pictory API: workspace rules that teach Cascade the API conventions, MCP integration for direct API calls, and example prompts.

## Prerequisites

* Windsurf installed
* A Pictory API key from [app.pictory.ai/api-access](https://app.pictory.ai/api-access) (starts with `pictai_`)

## Setup

<Steps>
  <Step title="Open your project in Windsurf">
    Open the project where you want to integrate the Pictory API.
  </Step>

  <Step title="Store your Pictory API key">
    Add the key to your shell profile (do not commit it):

    ```bash theme={null}
    echo 'export PICTORY_API_KEY="pictai_your_key_here"' >> ~/.zshrc
    source ~/.zshrc
    ```

    Restart Windsurf after setting the variable.
  </Step>

  <Step title="Create workspace rules">
    Windsurf reads `.windsurf/rules.md` from the project root. Create the directory:

    ```bash theme={null}
    mkdir -p .windsurf
    ```
  </Step>

  <Step title="Add the Pictory rules file">
    Use the template in the next section to populate `.windsurf/rules.md`.
  </Step>
</Steps>

## Recommended Windsurf Rules

Create `.windsurf/rules.md`:

```markdown theme={null}
# Pictory API workspace rules

## About this project
This project integrates with the Pictory API to create videos programmatically. Cascade should reference the rules below on every interaction touching API calls.

## API conventions

- **Base URL:** `https://api.pictory.ai/pictoryapis`
- **Authentication:** `Authorization: $PICTORY_API_KEY` header. **The key value is raw — do NOT use a Bearer prefix.**
- **API key format:** Always starts with `pictai_`. Get it from https://app.pictory.ai/api-access.
- **Content-Type:** All POST requests use `application/json`.

## Primary endpoints

| Endpoint | Purpose |
|---|---|
| `POST /v2/video/storyboard` | Create a storyboard preview |
| `POST /v2/video/storyboard/render` | Render final video directly |
| `POST /v2/projects/{projectid}/render` | Re-render an existing project |
| `GET /v1/jobs/{jobid}` | Fetch job status and output |
| `GET /v1/brands/video` | List video brand kits |
| `GET /v1/avatars` | List AI avatars |

## Field rules

- `videoName` is required on all render endpoints.
- `brandId` and `brandName` are **mutually exclusive** — never include both.
- `smartLayoutId` and `smartLayoutName` are mutually exclusive.
- `subtitleStyleId` and `subtitleStyleName` are mutually exclusive.
- API-rendered jobs do NOT appear in My Projects unless `saveProject: true` is set, OR an existing `projectId` is passed as `templateId`.
- Supported `language` values: `zh, nl, en, fr, de, hi, it, ja, ko, mr, pt, ru, es, ta`.

## Job lifecycle

1. Submit a render → receive `jobId`.
2. Either poll `GET /v1/jobs/{jobid}` every 10–30 seconds, OR pass a `webhook` URL in the request body.
3. When `status === "completed"`, the video URL is in `data.videoURL`.

## Reference documentation

- Full docs: https://docs.pictory.ai/llms-full.txt
- OpenAPI spec: https://docs.pictory.ai/openapi.json

## Coding conventions

- Read `PICTORY_API_KEY` from environment variables — never inline.
- Polling intervals must be 10–30 seconds.
- Always check `data.status` before reading `data.videoURL`.
```

## Connecting via MCP

Windsurf's Cascade supports MCP servers natively. To let Cascade call the Pictory API as structured tools, connect the Pictory MCP server.

1. Open Windsurf settings → **Cascade** → **Model Context Protocol**.
2. Add the Pictory MCP server configuration (details at [Pictory MCP Server](https://pictory.ai/pictory-mcp-server-api)).
3. Reload Cascade to pick up the new tools.

Once connected, Cascade can invoke Pictory endpoints directly without generating code first.

## Example Prompts

* "Build a Node.js worker that consumes a queue of video render requests and submits each one to Pictory. Use the OpenAPI spec at [https://docs.pictory.ai/openapi.json](https://docs.pictory.ai/openapi.json) for the request shape."
* "Add a unit test for my `submitPictoryRender` function that mocks the API response."
* "Trace through this 401 error — why is my Pictory API request being rejected?"
* "Generate a webhook handler that receives Pictory's completion callback and uploads the rendered video to S3."

## Troubleshooting

<AccordionGroup>
  <Accordion title="Cascade Suggests Bearer Authorization">
    **Cause:** Default LLM bias toward Bearer flows.

    **Resolution:** Reinforce the rule in `.windsurf/rules.md`. If Cascade still suggests Bearer mid-session, correct it once and Cascade will adapt.
  </Accordion>

  <Accordion title="MCP Tools Do Not Appear in Cascade">
    **Cause:** MCP server not running or misconfigured.

    **Resolution:** Verify the MCP server URL and credentials, restart Windsurf, and check the Cascade panel for tool registration errors.
  </Accordion>

  <Accordion title="Cascade Polls Too Aggressively">
    **Cause:** Default LLM tendency to write tight polling loops.

    **Resolution:** The rules file specifies 10–30 second polling. If Cascade still generates a 1-second loop, paste the snippet back and say "follow the polling interval rule in `.windsurf/rules.md`."
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Use Pictory with an LLM" icon="sparkles" href="/guides/llm-integration/use-pictory-with-llm">
    System prompts, MCP, and example flows
  </Card>

  <Card title="End-to-End Recipes" icon="book-open" href="/guides/recipes/end-to-end-recipes">
    Ready-to-run JSON payloads
  </Card>

  <Card title="Claude Code Setup" icon="terminal" href="/ai-tools/claude-code">
    Same setup, for Claude Code users
  </Card>

  <Card title="Cursor Setup" icon="arrow-pointer" href="/ai-tools/cursor">
    Same setup, for Cursor users
  </Card>
</CardGroup>
