Docs
Godance is an OpenAI-compatible REST API. If you've shipped against the OpenAI SDK, you already know the request shape of every endpoint below, and chat is drop-in: same JSON, same streaming format. Image and video generation run as async jobs, and errors come back as RFC 7807 problem details; see OpenAI SDK compatibility.
Get to first call in three steps
- Create an account and mint an API key in Settings → API Keys (returned in plaintext once — save it).
- Top up with card, ACH, or SEPA (Stripe), or USDT (NOWPayments). Same balance, same API.
-
Point your OpenAI SDK at
https://api.godance.ai/v1and start switchingmodelvalues.
Endpoint reference
- POST /v1/chat/completions — streaming + non-streaming
- POST /v1/images/generations — async: returns a job_id to poll, or pass webhook_url
- POST /v1/videos/generations — async-only, signed webhook
- GET /v1/jobs/{id} — async job status
- CRUD /v1/keys — API key management
- POST /v1/billing/topup — credit top-up via Stripe Checkout
- GET /v1/webhooks/secret — signing secret + verification guide
POST /v1/chat/completions
OpenAI's chat completions contract. Set "stream": true
for server-sent events; otherwise the response is a single JSON object.
model(required) — any text model from the model catalog.messages(required) — array of objects withroleandcontent;contentis a plain string.max_tokens,temperature— optional.stream— optional, defaults tofalse.
Non-streaming returns 200 with a
chat.completion object
(choices[].message, finish_reason,
usage). Streaming returns
text/event-stream: one
chat.completion.chunk per event, then
data: [DONE]. Other OpenAI parameters
(tools, top_p,
response_format, …) aren't supported and are ignored.
curl https://api.godance.ai/v1/chat/completions \
-H "Authorization: Bearer $GODANCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "Hello"}],
"stream": true
}' POST /v1/images/generations
The request shape is OpenAI's. Every image model runs as an async job, so this endpoint
always answers 202 Accepted with a
job_id — it never returns image data inline. Poll
GET /v1/jobs/{id}
for the result, or pass webhook_url and receive a
signed POST
when the images are ready.
model,prompt(required).size,n,style,quality— optional, as in OpenAI's API;ndefaults to 1.webhook_url— optional Godance extension; where to POST the completion event.
The full cost (per-image price × n) is reserved from your
balance when the job is accepted and refunded automatically if generation fails. An
insufficient balance returns 402.
curl https://api.godance.ai/v1/images/generations \
-H "Authorization: Bearer $GODANCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "flux-2-pro",
"prompt": "a lighthouse at dusk, watercolor",
"n": 1,
"webhook_url": "https://example.com/hooks/godance"
}' HTTP/1.1 202 Accepted
{
"job_id": "6f1c0b9e-2d4a-4c3b-9a57-0e8d4b2f7c11",
"status": "QUEUED",
"poll_url": "/v1/jobs/6f1c0b9e-2d4a-4c3b-9a57-0e8d4b2f7c11"
} POST /v1/videos/generations
Always async — video takes minutes, longer than an HTTP request should wait. The response
is the same 202 + job_id body
as for images; poll the job or pass webhook_url.
model,prompt(required).size— optional output resolution.seconds— optional clip length, defaults to 5.n— optional number of clips, defaults to 1.webhook_url— optional; where to POST the completion event.
Cost is the model's per-second rate × seconds ×
n, reserved up front and refunded if generation fails.
GET /v1/jobs/{id}
Returns one async job. GET /v1/jobs lists all of your jobs,
newest first. A job ID that isn't yours returns 404.
Fields are camelCase:
status—QUEUED→RUNNING→DONEorFAILED.outputUrl— set onceDONE: a time-limited signed URL to the first output, so copy the file to your own storage. Whenn> 1, the webhook payload lists every output.errorMessage— set whenFAILED; the reserved credit is refunded.estimatedCostCents,actualCostCents— integer cents.id,modality,provider,model,createdAt,startedAt,completedAt— timestamps are ISO 8601.
CRUD /v1/keys
Send your key as Authorization: Bearer gd_live_….
A key calls the model API only: chat completions, image and video generations,
jobs and usage. Everything else, these endpoints included, needs a signed-in
session; a key gets 403 there.
Create keys in the dashboard or with these endpoints:
-
POST /v1/keyswithname(required) and optionalscopes→201withid,name,prefix,plaintext,createdAt.plaintextis the key itself and is returned only this once. -
GET /v1/keys→ your keys withid,name,prefix,scopes,active,createdAt,lastUsedAt,expiresAt. Never includes the key. -
DELETE /v1/keys/{id}→204; the key stops working immediately. Unknown IDs return404.
An unknown, inactive or expired key returns 401. A key
restricted to an IP allowlist returns 403 from any other
address.
POST /v1/billing/topup
Usage is paid from a prepaid credit balance. A top-up returns a hosted checkout URL; the credit lands on your balance once the payment provider confirms the payment.
-
POST /v1/billing/topupwithamountCentsand optionalsave_card→201withsessionId,checkoutUrl,amountCents. Send the user tocheckoutUrl(Stripe Checkout).save_card: truekeeps the card on file for auto-recharge. -
POST /v1/billing/nowpayments/topupwithamountCents→ same response; the checkout URL is a NOWPayments page for paying in USDT. -
GET/PUT /v1/billing/auto-rechargewithenabled,threshold_cents,topup_cents— top up automatically when the balance falls below the threshold. Needs a card saved withsave_card(409otherwise).
An amount outside the allowed range returns 400; the
error detail states the range.
GET /v1/webhooks/secret
Image and video jobs submitted with a webhook_url get a
JSON POST to that URL when they complete. Each account has one signing secret:
-
GET /v1/webhooks/secret→secret(whsec_…) andheader(X-Godance-Signature). The secret is created on first call. -
POST /v1/webhooks/secret/rotate→ a new secret. For the next 24 hours deliveries are signed with both the new and the previous secret.
The delivery body carries:
event—image.generation.completedorvideo.generation.completed.jobId,costCents,createdAt(Unix seconds).imagesorvideos— one object per output, each with a time-limitedurl(images also carryrevisedPrompt).
Deliveries are sent once, on success, with a 10-second timeout and no retries. A failed
job sends no webhook — if one doesn't arrive, poll
GET /v1/jobs/{id}.
Webhook signature verification
Outbound webhooks carry an X-Godance-Signature
header in Stripe format: t=<unix>,v1=<hex>[,v1=<hex>...].
Each v1 is HMAC-SHA256 of
<t>.<raw body>, so verify against the raw
request body before parsing it. During the 24-hour grace window after a secret rotation, two
v1= entries are included — verify against
your stored secret and accept on ANY match.
import hmac, hashlib
def verify(payload, header, secret):
t = int(header.split(',')[0][2:])
sigs = [p[3:] for p in header.split(',') if p.startswith('v1=')]
expected = hmac.new(
secret.encode(), f"{t}.{payload}".encode(),
hashlib.sha256
).hexdigest()
return any(hmac.compare_digest(expected, s) for s in sigs) OpenAI SDK compatibility
Point the OpenAI SDK at https://api.godance.ai/v1 and use
a Godance key as the API key.
- Works unchanged: chat completions, streaming and
non-streaming, and
GET /v1/models. Catalog entries carry an extragodanceobject (modality, list price, platform fee) that OpenAI clients ignore. - Same request, different response: image and video
generation return
202+job_idinstead of the finished output, so the SDK's typed result won't contain images. Call these endpoints with a plain HTTP client (or your SDK's raw-response mode) and readjob_id. - Errors: non-2xx responses use RFC 7807
application/problem+jsonbodies (title,status,detail) rather than OpenAI's error object. Status codes keep their usual meaning —400invalid request,401bad key,402insufficient credit or spending cap reached,404unknown model or job — so SDKs still raise their usual status errors.
Questions? Email us.