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

# OpenAI-compatible AI Gateway (beta)

> Use Square Cloud's hosted cubic model in your own products through the OpenAI-compatible POST /v2/ai/chat/completions, with tool calling and web search.

<ParamField header="Authorization" type="string" placeholder="API Key" required>
  The API key for your account. You can find this in your [account settings](https://squarecloud.app/en/account/security).
</ParamField>

Requires an API key with the `ai:chat` [scope](/en/api-reference/authentication#scopes).

The AI Gateway lets you use Square Cloud's hosted AI model inside your **own** products (chatbots, assistants, automations) through an **OpenAI-compatible** chat completions endpoint. If your code already speaks the OpenAI API, it speaks the AI Gateway too: point the SDK at our base URL, use your account API key, and set the model to `cubic`.

<Note>
  The AI Gateway is in **beta with free early access**: during the beta there is no extra charge, and usage counts only against the gateway's own token limits. Limits and plan availability may change when the beta ends.
</Note>

## How to connect

* **Base URL:** `https://api.squarecloud.app/v2/ai`
* **API key:** your account API key (the same one used by the Square Cloud API and CLI, from the [account page](https://squarecloud.app/account)). The `Authorization` header is accepted with or without the `Bearer ` prefix.
* **Model:** `cubic`, Square Cloud's hosted model, the same one powering the dashboard AI assistant.

## Plans and limits

Every request bills its real tokens against the gateway's **own token limits**: a daily limit, reset at 00:00 UTC, and a weekly limit of 4x the daily one, reset on Monday at 00:00 UTC. They are separate from the dashboard AI assistant's limits, so gateway traffic never uses up the assistant's allowance, and vice versa. Standard and Pro also have a daily request ceiling, and every plan has a daily fair-use allowance on the gateway, sized for moderate use (a guard for unattended keys, based on what the requests cost to serve); both reset at 00:00 UTC.

| Plan | Tokens per day | Tokens per week | Requests per day | Fair-use allowance | Context window | Max output | Concurrent requests | Pacing between requests |
| - | - | - | - | - | - | - | - | - |
| Standard | 2.5M | 10M | 1,000 | base | 16,384 tokens | 4,096 | 1 | 5s |
| Pro | 5M | 20M | 5,000 | 2x base | 24,576 tokens | 6,144 | 1 | 2s |
| Enterprise | 10M to 20M | 40M to 80M | unlimited | 5x base | 32,768 tokens | 8,192 | 2 | none |

Every Standard plan size has the same gateway limits, and so does every Pro size. Enterprise token limits grow with the plan: 10M tokens per day on Enterprise 32, 12M on Enterprise 48, 14M on Enterprise 64, 16M on Enterprise 96 and 20M on Enterprise 128 and above, with 4x that per week.

<Info>Hobby plans (and accounts without a plan) do not have AI Gateway access: upgrading to Standard or above enables it.</Info>

## Request contract

<ParamField body="model" type="string">
  Accepted for SDK compatibility; the gateway always answers as `cubic`.
</ParamField>

<ParamField body="messages" type="array" required>
  OpenAI-style messages with roles `system`, `user`, `assistant` and `tool`. Content must be a **string**: this endpoint is text only, so a multi-part array (`image_url`, `input_audio`, `file`) is rejected with `400 multimodal_not_supported`. Up to **100 messages** per request.
</ParamField>

<ParamField body="max_completion_tokens" type="number">
  OpenAI's current name for the answer's token limit, the one the OpenAI SDKs send. It wins over `max_tokens` when both are present. Silently clamped to your plan's output ceiling.
</ParamField>

<ParamField body="max_tokens" type="number">
  The legacy name, still accepted. Silently clamped to your plan's output ceiling.
</ParamField>

<ParamField body="temperature" type="number">
  From 0 to 2.
</ParamField>

<ParamField body="tools" type="array">
  Function calling in the standard OpenAI format, up to **32 tool definitions**. Tool calls come back as `finish_reason: "tool_calls"`, and you send results back as `role: "tool"` messages.
</ParamField>

<ParamField body="tool_choice" type="string | object">
  Standard OpenAI `tool_choice` values.
</ParamField>

Unknown parameters are ignored, with two deliberate exceptions: `audio` and a `modalities` value other than `["text"]` are **rejected** rather than ignored, so a request for spoken output never comes back as silent text.

**Text in, text out.** Images, audio and files are not accepted on any plan, and this is a product decision rather than a temporary gap. Send text and read text back.

**Not supported yet:** streaming (`stream: true` returns `400 stream_not_supported`).

### Built-in web search

The model decides on its own to search the web when the conversation asks for current or external information. Searches run server-side, and only the final answer is returned, citing result URLs. If you declare your own tool named `web_search`, yours replaces the built-in one.

<RequestExample>
  ```javascript JavaScript (OpenAI SDK) theme={"system"}
  import OpenAI from "openai";

  const client = new OpenAI({
    baseURL: "https://api.squarecloud.app/v2/ai",
    apiKey: process.env.SQUARECLOUD_API_KEY,
  });

  const completion = await client.chat.completions.create({
    model: "cubic",
    messages: [
      { role: "system", content: "You are a helpful assistant." },
      { role: "user", content: "Explain what Square Cloud is in one sentence." },
    ],
  });

  console.log(completion.choices[0].message.content);
  ```

  ```python Python (OpenAI SDK) theme={"system"}
  from openai import OpenAI

  client = OpenAI(
      base_url="https://api.squarecloud.app/v2/ai",
      api_key="YOUR_API_KEY",
  )

  completion = client.chat.completions.create(
      model="cubic",
      messages=[
          {"role": "system", "content": "You are a helpful assistant."},
          {"role": "user", "content": "Explain what Square Cloud is in one sentence."},
      ],
  )

  print(completion.choices[0].message.content)
  ```

  ```bash cURL theme={"system"}
  curl --request POST \
    --url https://api.squarecloud.app/v2/ai/chat/completions \
    --header 'Authorization: YOUR_API_KEY' \
    --header 'Content-Type: application/json' \
    --data '{
      "model": "cubic",
      "messages": [
        { "role": "user", "content": "Explain what Square Cloud is in one sentence." }
      ]
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json theme={"system"}
  {
    "id": "chatcmpl-9f2c1a7e4b3d8f6a0c5e2d1b",
    "object": "chat.completion",
    "created": 1754179200,
    "model": "cubic",
    "choices": [
      {
        "index": 0,
        "message": {
          "role": "assistant",
          "content": "Square Cloud is a cloud platform that hosts your applications, bots, websites and databases with zero infrastructure setup."
        },
        "finish_reason": "stop"
      }
    ],
    "usage": {
      "prompt_tokens": 28,
      "completion_tokens": 24,
      "total_tokens": 52
    }
  }
  ```
</ResponseExample>

## Errors

Every error uses the OpenAI shape `{ "error": { "message", "type", "param", "code" } }`, including authentication, scope, rate-limit, invalid-body, `500` and `503` errors, and the `code` is always lowercase.

| Status | Code | What it means / what to do |
| - | - | - |
| 401 | `access_denied` | The API key is missing, invalid, revoked or expired. |
| 403 | `upgrade_required` | The plan has no AI Gateway access (Hobby or no plan). Upgrade to Standard or above. |
| 403 | `missing_scope` | The API key lacks the scope this endpoint needs. |
| 403 | `resource_not_allowed` | The API key is restricted to resources that don't cover this request. |
| 400 | `invalid_json_body` / `invalid_messages` / `invalid_tools` / `invalid_tool_choice` / `invalid_temperature` / `invalid_max_tokens` | Malformed request body: fix the flagged field. |
| 400 | `stream_not_supported` | Remove `stream: true`; streaming is not available yet. |
| 400 | `multimodal_not_supported` | The endpoint is text only. Send each message's `content` as a string, and drop `audio` or any `modalities` beyond `["text"]`. |
| 400 | `context_length_exceeded` | Messages plus tool definitions exceed the plan's context window. Shorten the history or upgrade. |
| 400 | `invalid_request` | The model backend refused the request: almost always a tool-calling protocol mistake (a `tool` message that does not answer a preceding `tool_calls`, duplicate call ids). |
| 413 | `payload_too_large` | The request body is larger than this endpoint accepts. Shorten the history. |
| 429 | `concurrent_limit_reached` | A request is already in flight; wait for it to finish (Enterprise allows 2 at once). |
| 429 | `rate_limit_exceeded` | Requests sent faster than the plan's pacing; add the delay client-side. |
| 429 | `daily_request_limit_reached` | The plan's daily request ceiling is reached (Standard 1,000 / Pro 5,000); it resets at 00:00 UTC. Enterprise has no ceiling. |
| 429 | `daily_spend_limit_reached` | The plan's daily fair-use allowance on the gateway is reached; it resets at 00:00 UTC. Pro has 2x and Enterprise 5x the base allowance. |
| 429 | `daily_limit_reached` | The gateway's daily token limit is spent; it resets at 00:00 UTC. An upgrade raises it. |
| 429 | `weekly_limit_reached` | The gateway's weekly token limit (4x the daily one) is spent; it resets on Monday at 00:00 UTC. An upgrade raises it. |
| 429 | `rate_limited` | The request limit of the account or API key was reached; wait and retry. |
| 500 | `internal_server_error` | Unexpected failure. Retry. |
| 503 | `server_overloaded` | Capacity is momentarily full, or the request passed the 90-second total deadline; retry shortly (OpenAI SDKs retry this automatically). |
| 503 | `daily_capacity_reached` | The AI Gateway's shared daily capacity, for the whole platform, is used up. It resets at 00:00 UTC; retrying before that doesn't help. |
| 503 | `database_unavailable` | The platform is briefly unavailable. Retry in a few seconds. |

Three of these look alike but mean different things:

* `429 daily_spend_limit_reached`: the daily limit of **your** key, set by your plan.
* `503 daily_capacity_reached`: the daily capacity of the **platform** for the gateway, shared by every customer.
* `503 server_overloaded`: a momentary overload, or a request that took longer than 90 seconds in total (provider queue, retries and search rounds included). Retry in a few seconds.

## Retries

Most `429` and `503` answers tell your client when to try again, through headers the OpenAI SDKs read:

| Code | Headers | What to expect |
| - | - | - |
| `429 rate_limit_exceeded` | `Retry-After` with the plan's pacing between requests, in seconds (Standard 5, Pro 2) | The OpenAI SDKs wait and retry on their own. |
| `429 daily_request_limit_reached`, `daily_spend_limit_reached`, `daily_limit_reached` and `503 daily_capacity_reached` | `Retry-After` with the seconds until 00:00 UTC, and `x-should-retry: false` | The SDK doesn't retry; wait for the reset. |
| `429 weekly_limit_reached` | `Retry-After` with the seconds until Monday at 00:00 UTC, and `x-should-retry: false` | The SDK doesn't retry; wait for the reset. |
| `503 server_overloaded` | `Retry-After: 2` | The OpenAI SDKs wait and retry on their own. |
| `429 concurrent_limit_reached` | No `Retry-After` | Retry when your request in flight finishes, or let the SDK's default retries handle it. |

The OpenAI SDKs honor a `Retry-After` of up to 60 seconds. A longer wait falls back to the SDK's own backoff, unless the answer also carries `x-should-retry: false`, which turns its automatic retries off. Without an OpenAI SDK, read `Retry-After` yourself and wait that many seconds before the next request.

## Frequently asked questions

<AccordionGroup>
  <Accordion title="Does it remember conversations?">
    No, the API is stateless, exactly like OpenAI's: send the conversation history in `messages` on every request.
  </Accordion>

  <Accordion title="Which model is it?">
    `cubic`, Square Cloud's hosted model. There is no model list to choose from; the `model` field is accepted for SDK compatibility.
  </Accordion>

  <Accordion title="Can I call it from an app hosted on Square Cloud?">
    Yes, that is the main use case. It is a normal HTTPS API, so it works from anywhere.
  </Accordion>

  <Accordion title="Does gateway usage affect my dashboard AI assistant?">
    No. The gateway has its own daily and weekly token limits, separate from the dashboard assistant's, so heavy gateway usage never uses up the assistant's allowance, and vice versa.
  </Accordion>
</AccordionGroup>

## Related

* SDKs: [`api.ai.chat()`](/en/sdks/js/ai) (JavaScript), [`client.ai.chat()`](/en/sdks/py/ai) (Python), [`c.AI.Chat()`](/en/sdks/go/ai) (Go)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.