---
title: "Quickstart"
description: "Generate your first SVG with the QuiverAI API, save it as a file, and open it in your browser."
icon: "rocket"
---

Create a compass icon with Arrow 2 through the Responses API and save the result as `compass.svg`.
This guide makes real, billable requests with a Production key. The API Platform's
built-in Quickstart uses a separate Test-key sandbox.

If you want to create directly in the QuiverAI App, start with the [App docs](/app).

1. **Prepare your project**

    Sign in to the [API Platform](https://platform.quiver.ai) and choose or create the
    [project](https://platform.quiver.ai/projects) that will own the integration.

    Check that your organization has sufficient funding in
    [Billing](https://platform.quiver.ai/billing). Ask a member with billing management permission
    to add funding if needed. See [API pricing](/developers/pricing) for charges.

2. **Create and store an API key**

    ![Create API key dialog with Production environment and a new service account selected](/blume-assets/content/developers/images/create-api-key.png)

    Create a **Production** key for your project in
    [API Keys](https://platform.quiver.ai/api-keys). Allow **Model catalog and Responses**
    (`catalog_read`) and the model you will use. This Responses example does not require a native
    SVG capability. A test key would answer this call from the
    [sandbox](/developers/guides/sandbox-and-test-keys) instead of a model.

    Copy the secret immediately; it is shown only once. Keep it server-side and never commit it to
    source control. Set it in the terminal where you will run the example:

    **macOS / Linux**

    ```bash
    export QUIVERAI_API_KEY="<your-key>"
    ```

    **Windows PowerShell**

    ```powershell
    $env:QUIVERAI_API_KEY="<your-key>"
    ```

3. **Check model availability**

    Read the catalog available to your organization. Use cURL 7.76 or later:

    **macOS / Linux**

    ```bash
    curl --fail-with-body https://api.quiver.ai/v1/models \
      --header "Authorization: Bearer $QUIVERAI_API_KEY"
    ```

    **Windows PowerShell**

    ```powershell
    curl.exe --fail-with-body https://api.quiver.ai/v1/models `
      --header "Authorization: Bearer $env:QUIVERAI_API_KEY"
    ```

    Continue when `data` contains a model with `id: "arrow-2"` and
    `"open_responses"` in its `supported_operations` list. Your key must also allow that model;
    appearing in the catalog does not grant the key access.

    If that model and operation are unavailable, use an authorized native model with the
    [Text to SVG](/developers/models/text-to-svg) or [Image to SVG](/developers/models/image-to-svg)
    guide instead. Those guides include the official `@quiverai/sdk` examples. Native requests also
    require the corresponding key capability, such as **Generate SVGs**.

4. **Generate and save an SVG**

    Responses returns tool calls for your application to handle. This example declares a
    `write_file` function that stages the latest SVG in memory, reports each tool result back to
    Arrow, and saves `compass.svg` only after a completed response has no more tool calls.

    The endpoint is stateless. The example sends `store: false` and replays input history on each
    turn rather than continuing from a stored response ID. See
    [Current limitations](/developers/guides/migrate-to-responses#current-limitations) for supported
    transports and request options.

    Use Node.js 22 or later. No packages are required. Save this as `generate.mjs`:

    ```javascript
    import { writeFile } from "node:fs/promises";

    const apiKey = process.env.QUIVERAI_API_KEY;
    if (!apiKey) throw new Error("Set QUIVERAI_API_KEY before running this example.");

    const input = [{
      type: "message",
      role: "user",
      content: "Create a minimal geometric compass icon in blue. Use write_file to stage the complete SVG as compass.svg, then confirm when finished.",
    }];
    const tools = [{
      type: "function",
      name: "write_file",
      description: "Stage compass.svg content. The caller saves the latest staged version after you finish.",
      parameters: {
        type: "object",
        properties: { path: { type: "string" }, content: { type: "string" } },
        required: ["path", "content"],
        additionalProperties: false,
      },
      strict: false,
    }];
    let svg;
    let finished = false;

    for (let turn = 0; turn < 5; turn += 1) {
      const response = await fetch("https://api.quiver.ai/v1/responses", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${apiKey}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          model: "arrow-2",
          input,
          tools,
          tool_choice: turn === 0 ? { type: "function", name: "write_file" } : "auto",
          stream: false,
          store: false,
          parallel_tool_calls: false,
        }),
      });
      if (!response.ok) {
        throw new Error(`Request failed (${response.status}): ${await response.text()}`);
      }
      const result = await response.json();
      if (result.status !== "completed" || result.error || result.incomplete_details) {
        throw new Error(`Generation did not complete (${result.status}). No file was saved.`);
      }
      const calls = result.output.filter((item) => item.type === "function_call");
      if (result.output.some((item) => item.type === "custom_tool_call")) {
        throw new Error("Unexpected custom tool call. No file was saved.");
      }
      if (calls.length === 0) {
        if (!svg) throw new Error("No SVG was staged.");
        await writeFile("compass.svg", svg, "utf8");
        finished = true;
        break;
      }
      for (const item of result.output) {
        if (item.type === "reasoning" && item.id) {
          input.push({ type: "reasoning", id: item.id });
        } else if (item.type === "message" || item.type === "function_call") {
          input.push(item);
        }
      }
      for (const call of calls) {
        if (call.name !== "write_file" || (call.status && call.status !== "completed")) {
          throw new Error("Unexpected or incomplete tool call. No file was saved.");
        }
        const args = JSON.parse(call.arguments);
        if (args.path !== "compass.svg" || typeof args.content !== "string" || !args.content.trim()) {
          throw new Error("Invalid write_file arguments. No file was saved.");
        }
        svg = args.content;
        input.push({
          type: "function_call_output",
          call_id: call.call_id,
          output: JSON.stringify({ path: "compass.svg", staged: true }),
        });
      }
    }
    if (!finished) throw new Error("Stopped after five requests. No file was saved.");
    console.log("Saved compass.svg. Open it in your browser to view the result.");
    ```

    Run it from the same directory:

    ```bash
    node generate.mjs
    ```

    The example allows at most five API requests, each of which can incur token charges. It keeps
    intermediate writes out of the filesystem and never uses a model-supplied destination path.
    An error, incomplete response, or exhausted request limit leaves no new file to publish.
    See [Migrate to Responses](/developers/guides/migrate-to-responses) for the raw HTTP request
    and tool-result replay shapes.

5. **Open your SVG**

    Open `compass.svg` in your browser or drag it into a vector editor. You should see a blue
    compass icon; the exact design varies between requests.

    The saved file contains the latest content staged by `write_file` after the tool loop finishes.
    A completed individual tool call can still be followed by a revision; reasoning text and
    partial argument deltas are not a finished SVG.

    If a request fails or returns no completed SVG, use
    [Errors and debugging](/developers/guides/errors-and-debugging) to interpret the response.

## Next steps

- [SDK compatibility](/developers/guides/migrate-to-responses#sdk-compatibility): configure Vercel AI SDK or an OpenAI Responses client.
- [API Reference](/api-reference/introduction): explore request options and response schemas.
- [Image to SVG](/developers/models/image-to-svg): vectorize an existing image with the native API.
- [API Platform](/developers/platform): manage your integration's keys, usage, limits, and data controls.
