The JSON API
Every method of the Voplica API is one HTTPS POST of a JSON body, and its answer is JSON. Any HTTP client works: no
SDK is needed. This is the unary JSON mode of the Connect protocol, so Connect
clients work on the same host too, in JSON or in binary protobuf.
A call
Section titled “A call”curl -X POST https://api.voplica.com/voplica.api.ai.model.ModelService/ListModels \ -H 'Content-Type: application/json' \ -d '{"limit": 2}'- The URL is
https://api.voplica.com/<package>.<Service>/<Method>: the method’s full name from the API reference or the protobuf reference. - The method is always
POST, with no query string. - The headers:
Content-Type: application/json, andAuthorization: Bearer <your key>when the method needs a key (Authentication). Acharset=utf-8parameter is accepted, and so is the Connect headerConnect-Protocol-Version: 1, which you never need. A body may be sent compressed, withContent-Encoding: gzip. - The body is the request message in protobuf’s JSON form.
{}is a request with every field unset. - The answer is
200withContent-Type: application/jsonand the response message in the same form.
The JSON mapping
Section titled “The JSON mapping”The request and the answer are the method’s protobuf messages, written as JSON the standard way:
- Field names take either spelling: the JSON one (
compatibleLoraModelFamily) or the one in the.protofile (compatible_lora_model_family), but not both for the same field. Answers use the JSON spelling. - Unknown fields are refused, with
400and a message that names the field, so a misspelt field name never passes unnoticed — except inside a request map such asworkflowInput(Generating images and videos). - 64-bit integers — timestamps, counts, credit amounts — are JSON strings in answers (
"permanentCreditsMilli": "2500000"). In requests they are accepted as strings or as numbers. Ids are strings. - Enums are written by name (
"FLUX_2_KLEIN_9B"). An unknown name is refused with400. - Unset values are still printed in answers: a field that holds a plain value, a list or a map appears with its
default (
0,"0"for a 64-bit integer,"",false,[],{}, or the enum’s zero value). Anoptionalfield, aoneoffield and a field that holds a message are left out when unset. - Bytes are base64.
- The body must be one valid JSON object: no duplicate keys, no comments and nothing after the closing brace.
Errors
Section titled “Errors”When a call fails, the answer is a JSON object with a code and a message, sent with a matching HTTP status:
{ "code": "invalid_argument", "message": "invalid JSON request: Cannot find field: compatibleLoraModelFamilyy in message voplica.api.ai.model.GetRecommendedBaseModelVariantRequest"}Branch on code, not on the HTTP status: the status only follows the code.
code |
HTTP status | For example |
|---|---|---|
invalid_argument |
400 | An unknown field, a wrong value, a body over the limit. |
out_of_range |
400 | |
unauthenticated |
401 | No key where one is needed, or a key that is not valid. |
permission_denied |
403 | A method a key may not call. |
not_found |
404 | The item does not exist (Model not found). |
unimplemented |
404 | |
canceled, deadline_exceeded |
408 | |
already_exists, aborted |
409 | |
failed_precondition |
412 | A run that cannot start: not enough Anytime or Earned credits. |
resource_exhausted |
429 | A per-account quota was reached. |
unavailable |
503 | A temporary failure. Retry. |
internal, unknown, data_loss |
500 |
A timeout you set yourself with the Connect-Timeout-Ms header ends as 503, not 408. Treat every 503 as
something to retry.
Retry a call that starts a run only with an idempotency key: ExecuteWorkflow takes idempotencyKey (letters,
digits and _, at most 30 characters), and a retry with the same key returns the run already started instead of
starting a second one.
Answers that are not JSON
Section titled “Answers that are not JSON”A few refusals happen before your request reaches a method, at the host’s edge or in front of the service. They are not JSON: plain text, or an empty body.
| HTTP status | When |
|---|---|
| 403 | The method is not served on this host (not available on the public gateway). |
| 404, empty | The path is not a method of the API. |
| 405 | The request has a connect query parameter. Send a POST with the message in its body. |
| 413 | The body is far over the limit and is refused before it is read. |
| 415 | The Content-Type is not JSON, binary Connect (application/proto) or gRPC-Web. |
| 503 | A service is down (no healthy upstream). Retry. |
So a client should read code from a JSON answer, and treat an answer that is not JSON by its HTTP status.
Limits
Section titled “Limits”- A request body is at most 1 MiB (1,048,576 bytes), counted after decompression. A larger body is refused with
400andinvalid_argument, and the message gives the limit. Files never travel inside a request: you pass their ids, such as those of your earlier runs’ outputs. Uploading files through the public API is planned. - Long work runs in the background. A call that starts a generation answers at once with an id, and you read the result with later calls, so no request has to stay open while the work runs.
Pagination
Section titled “Pagination”Most list methods take a page size, limit, and answer with two tokens, nextToken and prevToken:
curl -X POST https://api.voplica.com/voplica.api.ai.model.ModelService/ListModels \ -H 'Content-Type: application/json' \ -d '{"limit": 2}'{ "models": [{ "id": "…" }, { "id": "…" }], "nextToken": "…", "prevToken": "…"}- The next page: send the same request with
"cursor": "<nextToken>". - The previous page: send
"cursor": "<prevToken>"and"before": true. - The end: a page with no items, and no tokens.
A few list methods page differently, for example by page number, and some return everything in one answer. Each method’s fields are in the reference.
Other clients
Section titled “Other clients”Connect clients speak this protocol natively, in JSON or in binary protobuf (Content-Type: application/proto), and
gRPC-Web clients work too. The native gRPC endpoint opens soon. Clients covers the clients for TypeScript,
Java, Python and Go, which give you type-safe requests and responses for this API, and Protobuf and gRPC
the definitions they are made from.