---
title: "Migrate to the Responses API"
description: "Decide when an existing native SVG integration should adopt the Responses API and migrate its request and result handling."
icon: "git-compare-arrows"
---

Use `POST /v1/responses` with a model whose catalog entry includes `open_responses`. Responses lets
your application declare functions or custom tools, handle the returned calls, and send results
back for another turn. Native SVG endpoints remain the simpler choice for a known SVG operation.

## Choose the right contract

| Need                                                       | Recommended API                                                                  |
| ---------------------------------------------------------- | -------------------------------------------------------------------------------- |
| Generate, vectorize, edit, or animate an SVG               | The corresponding native `/v1/svgs/*` endpoint                                   |
| Let Arrow choose among functions your application provides | `/v1/responses` with declared tools and `tool_choice: "auto"`                    |
| Request a specific caller function                         | `/v1/responses` with `tool_choice: { "type": "function", "name": "write_file" }` |
| Continue after executing a tool                            | `/v1/responses`, replaying messages, calls, and matching tool results            |

Native endpoints remain supported; migration is conditional, not a prerequisite for existing
integrations.

## SDK compatibility

Responses uses the [Open Responses](https://www.openresponses.org/) wire format. Compatibility
covers the supported HTTP Responses surface, not every OpenAI endpoint or SDK feature.

| Client                               | Configuration                                                                                                                                                    |
| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Vercel AI SDK                        | Prefer `@ai-sdk/open-responses` with the complete `https://api.quiver.ai/v1/responses` URL. Streaming and non-streaming tool loops are supported.                |
| OpenAI JavaScript and TypeScript SDK | Set `baseURL: "https://api.quiver.ai/v1"`, provide your QuiverAI API key, and use `client.responses.create`. Use the Responses API rather than Chat Completions. |

For Vercel AI SDK integrations, configure the provider on your server:

```typescript
import { createOpenResponses } from "@ai-sdk/open-responses";

const apiKey = process.env.QUIVERAI_API_KEY;
if (!apiKey) throw new Error("Set QUIVERAI_API_KEY before creating the provider.");

const quiver = createOpenResponses({
  name: "quiver",
  url: "https://api.quiver.ai/v1/responses",
  apiKey,
});
const model = quiver("arrow-2");
```

Confirm model access before using this configuration. With any SDK, disable stored responses and
response-ID continuation, and avoid options that add `include`, `background`, or hosted tools.
Some OpenAI-specific reasoning options add unsupported fields; prefer the Open Responses provider
when integrating through Vercel AI SDK.

TanStack Start is an application framework, not a separate model protocol. Call these clients
from server-side code in a TanStack Start application and keep the API key out of browser code.

## Current limitations

The following limits apply regardless of which SDK sends the request:

| Feature                        | Current behavior                                                                                                                                                                                                      |
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Transport                      | HTTP with a JSON response or SSE streaming. WebSockets are not supported.                                                                                                                                             |
| Response storage and retrieval | Stateless requests only. Omit `store` or send `store: false`; there is no stored-response retrieval endpoint.                                                                                                         |
| Conversation continuation      | Replay the full conversation input, including prior messages, returned calls, matching tool results, and opaque reasoning IDs. Omit `previous_response_id` or send `null`; response-ID continuation is not supported. |
| Tools                          | Declare `function` or `custom` tools and execute them in your application. Hosted tools, including old `quiver:*` tools, are not supported.                                                                           |
| Other options                  | `background`, `include`, `websocket`, and unknown top-level fields are rejected.                                                                                                                                      |

`store: true`, a non-null `previous_response_id`, and unsupported request fields return
`400 invalid_request` before model execution. Organization data policy cannot enable these
features. Stateless Responses behavior is separate from metadata and inference-retention policy;
see [Data controls](/developers/platform/data-controls).

## Before migrating

1. Call `GET /v1/models` and choose a model whose `supported_operations` includes `open_responses`.
   The catalog describes organization availability; the key must separately allow the model.
2. Use a key whose authority permits **Model catalog and Responses** (`catalog_read`) and your
   chosen model. Native SVG capability authority is not required for a Responses call. The
   sandbox does not serve `/v1/responses`, so a Test key answers `404` there — see
   [Sandbox and test keys](/developers/guides/sandbox-and-test-keys).
3. Read the model's live `billing.rates`. Each Responses request in a tool loop can incur token
   charges; keep a limit on the number of requests your application makes.

## Map the request

A native generation request names the operation in its URL and returns the generated SVG. A
Responses request declares tools that your application implements. `write_file` below is an
application-defined function, not a hosted filesystem service. Save this body as `request.json`:

```json
{
  "model": "arrow-2",
  "input": "Create a minimal geometric compass icon in blue and stage it as compass.svg using write_file.",
  "tools": [
    {
      "type": "function",
      "name": "write_file",
      "description": "Stage compass.svg content for the caller to save after refinement is complete.",
      "parameters": {
        "type": "object",
        "properties": { "path": { "type": "string" }, "content": { "type": "string" } },
        "required": ["path", "content"],
        "additionalProperties": false
      },
      "strict": false
    }
  ],
  "tool_choice": { "type": "function", "name": "write_file" },
  "stream": false,
  "store": false,
  "parallel_tool_calls": false
}
```

Send one turn with cURL:

```bash
curl --fail-with-body https://api.quiver.ai/v1/responses \
  --header "Authorization: Bearer $QUIVERAI_API_KEY" \
  --header 'Content-Type: application/json' \
  --data @request.json \
  --output response.json
```

This command receives the model's response; it does not execute a tool or finish a multi-turn
integration. The [Quickstart](/developers/quickstart) includes a complete bounded tool loop.

Old `quiver:*` hosted-tool definitions and their `result.data[].svg` receipts are not this
contract. See [Current limitations](#current-limitations) when adapting an existing client.

## Map the result

Native JSON responses return final SVGs in `data[].svg`. Responses can return `function_call`,
`custom_tool_call`, and assistant message items in `output`. A function call contains a `name`,
`call_id`, and JSON-encoded `arguments`, for example:

```json
{
  "type": "function_call",
  "id": "fc_1",
  "call_id": "call_1",
  "name": "write_file",
  "status": "completed",
  "arguments": "{\"path\":\"compass.svg\",\"content\":\"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\"/>\"}"
}
```

Validate the function name and arguments before handling it. Restrict file destinations in your
application; never execute arbitrary paths or commands from model output.

## Continue the tool loop

After handling a function call, append the relevant prior messages, the `function_call` item, and
a `function_call_output` whose `call_id` matches it. For the staging function above, the result is:

```json
{
  "type": "function_call_output",
  "call_id": "call_1",
  "output": "{\"path\":\"compass.svg\",\"staged\":true}"
}
```

Preserve returned opaque reasoning IDs in their original history order as
`{ "type": "reasoning", "id": "<returned-id>" }`; do not send private reasoning text or request
encrypted reasoning. Send the history as `input` with the same model and tool definitions. Use `tool_choice: "auto"`
on follow-up turns so the model can finish without another call. Custom tools use
`custom_tool_call_output` with the corresponding `call_id`.

A completed tool call is not necessarily the last revision of an asset. Publish the latest staged
content only after a completed response has no pending calls. An exhausted request limit, failed
response, or incomplete response must not publish staged content as finished work. Do not use
reasoning text as an artifact.

For streaming integrations, collect function-argument or custom-input deltas, then handle complete
calls from the terminal response. Do not execute partial arguments. See
[Errors and debugging](/developers/guides/errors-and-debugging) for terminal
failure handling.

## Roll out safely

Keep the native path available while validating the Responses path for an authorized project and
key. Compare final SVG handling, token-usage accounting, timeout behavior, and retry policy before
routing production traffic. A test key cannot validate `/v1/responses`; use a narrowly authorized
Production key.
