GET STARTED INTRODUCTION
Build with intelligence.
Power your next application with the ProsGrow API. Familiar tools, transparent pricing, and a clear path from your first request to production.
Start building in minutes.
Choose a model, add your API key, and send a request with Python, JavaScript, or curl. The API uses the OpenAI-compatible chat completions format.
Model access is specific to your account. Check your model permissions and available balance in the console before sending requests.
Create an API key
Sign in to your console, open API keys, and create a key with access to your model. Keep the key in your server environment.
Set up your environment
Export your key and API base URL in your terminal. Python and JavaScript examples read these variables automatically.
export OPENAI_BASE_URL="https://api.prosgrow.ai/v1"
export OPENAI_API_KEY="sk-...your ProsGrow API key..."
# Generate once for a new request. Reuse this value when retrying it.
export REQUEST_ID="$(uuidgen)"
Send your first request
The examples use deepseek-v4-flash. Use a model ID from the public catalog that is enabled for your key.
Install the SDK: pip install openai
import uuid
from openai import OpenAI
client = OpenAI() # reads OPENAI_BASE_URL / OPENAI_API_KEY from the environment
request_id = str(uuid.uuid4()) # reuse for retries of this request
resp = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[{"role": "user", "content": "Say hello."}],
extra_headers={"Idempotency-Key": request_id},
)
print(resp.choices[0].message.content)
Install the SDK: npm install openai
import OpenAI from "openai";
import { randomUUID } from "node:crypto";
const client = new OpenAI({
baseURL: process.env.OPENAI_BASE_URL,
apiKey: process.env.OPENAI_API_KEY,
});
const requestId = randomUUID(); // reuse for retries of this request
const response = await client.chat.completions.create(
{
model: "deepseek-v4-flash",
messages: [{ role: "user", content: "Say hello." }],
},
{ headers: { "Idempotency-Key": requestId } },
);
console.log(response.choices[0].message.content);
Run directly in your terminal.
curl https://api.prosgrow.ai/v1/chat/completions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $REQUEST_ID" \
-d '{
"model": "deepseek-v4-flash",
"messages": [{"role": "user", "content": "Say hello."}]
}'
For retry protection, the examples send an Idempotency-Key. Create one key per logical request and reuse it when retrying that request. Learn how retries work →
Authenticate your requests.
Send your ProsGrow API key in the Authorization header. A stock OpenAI SDK works once you configure the base URL and key.
Authorization: Bearer <your ProsGrow key>
Create and manage keys from API keys. Use environment variables on your server; keep API keys out of browser code and source control.
The right model for your workload.
The public model catalog contains model IDs, capabilities, supported endpoints, context limits, and pricing. It is available without authentication and reflects the catalog published by this environment.
Published pricing and model availability are separate. Review the model's capabilities and your account permissions before sending requests.
Stream as the model responds.
Set stream=True to receive server-sent events (SSE). Add stream_options={"include_usage": True} to request a final usage chunk.
import uuid
from openai import OpenAI
client = OpenAI()
request_id = str(uuid.uuid4()) # reuse for retries of this request
stream = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[{"role": "user", "content": "Write a haiku about GPUs."}],
stream=True,
stream_options={"include_usage": True},
extra_headers={"Idempotency-Key": request_id},
)
for chunk in stream:
if chunk.choices:
delta = chunk.choices[0].delta.content or ""
print(delta, end="", flush=True)
if chunk.usage is not None:
cost_usd = getattr(chunk.usage, "cost_usd", None)
if cost_usd is not None:
print(f"\nCost: ${cost_usd}")
The final usage chunk can have an empty choices array. Read streaming cost from usage.cost_usd when present; the final cost is not available when response headers are first sent.
Make repeat requests more efficient.
Repeated prompt prefixes can benefit from prompt caching. Where a model publishes a cached-input price, reported cached tokens are billed at that rate instead of the full input rate.
Structure the prompt: static first, variable last
- Put system instructions, tool definitions, examples, and reference documents first. Put the changing user question last.
- Keep tool and schema ordering byte-stable between requests.
- Avoid a timestamp, request id, nonce, or randomly ordered data in your reusable prefix.
- Grow chat history append-only; rewriting earlier turns changes the prefix.
Use a stable prompt cache key
prompt_cache_key is a routing hint, not a storage reservation and not a guarantee. Choose a stable key per workload or prompt template and change it when the template changes. Keys are scoped per organization.
import uuid
from openai import OpenAI
client = OpenAI()
STATIC_PREAMBLE = "You are a helpful support assistant. Answer clearly and concisely."
question = "How can I check my order status?"
request_id = str(uuid.uuid4()) # reuse for retries of this request
resp = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[
{"role": "system", "content": STATIC_PREAMBLE}, # static prefix FIRST
{"role": "user", "content": question}, # variable content LAST
],
prompt_cache_key="support-bot-v3",
# older SDKs: extra_body={"prompt_cache_key": "support-bot-v3"}
extra_headers={"Idempotency-Key": request_id},
)
print(resp.usage.prompt_tokens_details) # cached_tokens, when the model reports it
# Generate once for a new request. Reuse this value when retrying it.
export REQUEST_ID="$(uuidgen)"
curl https://api.prosgrow.ai/v1/chat/completions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $REQUEST_ID" \
-d '{
"model": "deepseek-v4-flash",
"prompt_cache_key": "support-bot-v3",
"messages": [
{"role": "system", "content": "...long, byte-stable instructions, tools and examples..."},
{"role": "user", "content": "What changed in my order?"}
]
}'
Cache hits are best-effort. A prefix can be evicted at any time, and not every model reports cache usage. We do not promise a hit rate or a discount percentage. Measure cached tokens and cache hit rate on your Usage page.
Use the tools you know.
Use the chat-completions request format with your existing SDK. Capabilities vary by model; check the catalog before enabling a feature.
| Capability | Parameters |
|---|---|
| Tool calling | tools, tool_choice |
| JSON output | response_format |
| Sampling | temperature, top_p |
| Response length | max_tokens, stop |
| Streaming | stream, stream_options |
Unknown or unsupported top-level fields are accepted and ignored by default; a deployment can enable strict rejection. Out-of-range parameter values are rejected with 400 invalid_request.
A small API. A lot you can build.
Use your configured base URL for inference. The OpenAPI 3.1 specification documents request schemas, response shapes, and error codes.
/v1/chat/completionsGenerate chat responses, with optional streaming.
/v1/modelsRead the public model catalog and prices. No authentication required.
/v1/balanceCheck prepaid balance and per-key token quota.
/v1/usageRead per-request usage line items.
/v1/requests/{id}Look up a billing receipt by stable request ID.
/v1/idempotency/{key}Look up a request state or receipt. Requires the ?model= parameter.
/v1/healthRun an end-to-end one-token health probe. No authentication required.
Retry with confidence.
Idempotency-Key is optional by default and recommended when you need retry deduplication. Generate one key for a logical request, keep its model and body unchanged, and reuse that key for retries. A new key identifies a new request.
| Request state | What happens on retry |
|---|---|
committed | HTTP 409 with a billing receipt; the original response body is not replayed. |
in_flight | HTTP 409 while the original request is still executing. |
| Failed | A genuinely failed request writes no billable row and can be retried. 5xx responses are not metered. |
Check request state with GET /v1/idempotency/{key}?model=… before retrying an ambiguous result.
Handle limits gracefully.
When the platform sheds load, it returns HTTP 429 with a Retry-After header in seconds. A rejected request was not executed and not billed.
- Honor
Retry-After, then retry with exponential backoff and jitter. - Keep the same
Idempotency-Keywhen retrying the same logical request. - Per-key monthly quotas and organization budgets also return 429 when exhausted. Check the error code and resolve the quota or balance before retrying.
Know what to do next.
Errors use the OpenAI-compatible envelope. Use the semantic code to decide whether to change the request, review your account, or retry.
{
"error": {
"message": "...",
"type": "...",
"code": "...",
"param": null,
"request_id": "..."
}
}
| Error code | Next step |
|---|---|
insufficient_org_balance | Review your balance and add funds. |
monthly_token_quota_exceeded | Review the API key's monthly quota. |
backend_at_capacity | Wait for the interval in Retry-After before retrying. |
unknown_endpoint | Check the path and method against the API reference. |
For the complete set of error codes, see the specification. Include the request ID when contacting support.
Your next request starts here.
Choose your model and create an API key.