---
title: "OpenAI Responses API subset on a PopNow text model"
method: POST
path: "/v1/responses"
tags: ["OpenAI Compatible"]
---

# OpenAI Responses API subset on a PopNow text model

`POST /v1/responses`

## Request

- Base URL: `https://api.popnow.ai`
- URL: `https://api.popnow.ai/v1/responses`
- Auth: HTTP bearer

Accepts the stateless subset of the OpenAI Responses API: `model`,
`input` (string or item array with `message`, `function_call` and
`function_call_output` items), `instructions`, `max_output_tokens`,
`temperature`, `top_p`, `tools` (function tools), `tool_choice`,
`text.format`, `reasoning.effort` and `stream`. The request is
translated to a chat completion internally. `previous_response_id`
is rejected with `400`; send the full history in `input` instead.
As on Chat Completions, sampling parameters the model does not
declare are ignored and listed in the `X-PopNow-Ignored-Params`
response header, and values outside the model's range or levels are
changed to the nearest accepted value and listed in
`X-PopNow-Adjusted-Params`.

Non-streaming calls return a `response` object with `output[]`
(`message` and `function_call` items) and `usage`. Streaming calls
emit `response.created`, `response.output_text.delta` and
`response.completed` events.

Billing: chat models are priced per token in credits (1 credit = $0.001), listed per 1M input and output
tokens in `credits` on `GET /api/v1/models` and `GET /v1/models`. When the request is accepted, the most it
can cost is held from your balance, computed from the input and `max_tokens` (the model's maximum output when
you omit it, so set `max_tokens` to keep holds small). When the reply ends you are charged its actual usage in
fractional credits, with no per-request minimum, and the rest of the hold is released. A balance below the
hold, or a key spend limit that would be exceeded, returns `402` before anything is sent to the model. A request
that fails or that the model refuses is refunded in full. The `X-PopNow-Task-Id` response header names the task;
`GET /api/v1/jobs/recordInfo` shows the final charge in `cost` (USD) and `exactCredits`. Message text is not
kept after the charge settles. Requests are forwarded to the model as sent and each model's own usage policy applies.

## Headers

- `Idempotency-Key` string

## Request body

- ResponsesRequest
  - `model` string, required
  - `input` union, required
    - string
    - object[]
  - `instructions` string
  - `max_output_tokens` integer
  - `temperature` number
  - `top_p` number
  - `tools` object[]
  - `tool_choice` union
    - string
    - object
  - `text` object
  - `reasoning` object
    - `effort` string
  - `stream` boolean

## Response `200`

One `response` object, or an SSE stream when `stream` is true.

- ResponseObject
  - `id` string, required
  - `object` 'response', required
  - `created_at` integer, required
  - `status` 'completed' | 'incomplete' | 'in_progress', required
  - `model` string, required
  - `output` object[], required
    - `id` string, required
    - `type` 'message' | 'function_call', required
    - `status` string, required
    - `role` string
    - `content` object[]
      - `type` 'output_text'
      - `text` string
      - `annotations` object[]
    - `call_id` string
    - `name` string
    - `arguments` string
  - `error` unknown
  - `incomplete_details` object, nullable
    - `reason` string
  - `usage` object
    - `input_tokens` integer
    - `output_tokens` integer
    - `total_tokens` integer

## Other responses

- `400`: Error in the OpenAI `{error:{message,type,param,code}}` shape. The HTTP status is the same one `/api/v1` would return. A content-policy refusal is HTTP 400 with `code: content_rejected`, so it can be told apart from a parameter error (`invalid_request` / `unsupported_parameter`, with `param` set when the error is about one field).
- `401`: Error in the OpenAI `{error:{message,type,param,code}}` shape. The HTTP status is the same one `/api/v1` would return. A content-policy refusal is HTTP 400 with `code: content_rejected`, so it can be told apart from a parameter error (`invalid_request` / `unsupported_parameter`, with `param` set when the error is about one field).
- `402`: Error in the OpenAI `{error:{message,type,param,code}}` shape. The HTTP status is the same one `/api/v1` would return. A content-policy refusal is HTTP 400 with `code: content_rejected`, so it can be told apart from a parameter error (`invalid_request` / `unsupported_parameter`, with `param` set when the error is about one field).
- `403`: Error in the OpenAI `{error:{message,type,param,code}}` shape. The HTTP status is the same one `/api/v1` would return. A content-policy refusal is HTTP 400 with `code: content_rejected`, so it can be told apart from a parameter error (`invalid_request` / `unsupported_parameter`, with `param` set when the error is about one field).
- `404`: Error in the OpenAI `{error:{message,type,param,code}}` shape. The HTTP status is the same one `/api/v1` would return. A content-policy refusal is HTTP 400 with `code: content_rejected`, so it can be told apart from a parameter error (`invalid_request` / `unsupported_parameter`, with `param` set when the error is about one field).
- `409`: Error in the OpenAI `{error:{message,type,param,code}}` shape. The HTTP status is the same one `/api/v1` would return. A content-policy refusal is HTTP 400 with `code: content_rejected`, so it can be told apart from a parameter error (`invalid_request` / `unsupported_parameter`, with `param` set when the error is about one field).
- `413`: Error in the OpenAI `{error:{message,type,param,code}}` shape. The HTTP status is the same one `/api/v1` would return. A content-policy refusal is HTTP 400 with `code: content_rejected`, so it can be told apart from a parameter error (`invalid_request` / `unsupported_parameter`, with `param` set when the error is about one field).
- `429`: Error in the OpenAI `{error:{message,type,param,code}}` shape. The HTTP status is the same one `/api/v1` would return. A content-policy refusal is HTTP 400 with `code: content_rejected`, so it can be told apart from a parameter error (`invalid_request` / `unsupported_parameter`, with `param` set when the error is about one field).
- `500`: Error in the OpenAI `{error:{message,type,param,code}}` shape. The HTTP status is the same one `/api/v1` would return. A content-policy refusal is HTTP 400 with `code: content_rejected`, so it can be told apart from a parameter error (`invalid_request` / `unsupported_parameter`, with `param` set when the error is about one field).
- `503`: Error in the OpenAI `{error:{message,type,param,code}}` shape. The HTTP status is the same one `/api/v1` would return. A content-policy refusal is HTTP 400 with `code: content_rejected`, so it can be told apart from a parameter error (`invalid_request` / `unsupported_parameter`, with `param` set when the error is about one field).

---

[API](https://skmtc.dev/popnow/apis/popnow-api.md) · [All operations](https://skmtc.dev/popnow/apis/popnow-api/llms.txt) · [OpenAPI document](https://skmtc.dev/popnow/apis/popnow-api/revisions/fede911a6e9b?raw)
