Model Endpoints
Every model on FlyMy.AI is addressed by its endpoint id, written as
{owner}/{model} - for example flymyai/google-gemini-25-flash. The endpoint
id maps directly into the URL path.
https://api.flymy.ai/api/v1/{owner}/{model}/{route}
Authentication
All routes take an API key in the X-API-KEY header:
-H "X-API-KEY: fly-***"
Create keys in your FlyMy.AI account settings. A key can call any public model plus every model you own.
Routes
| Route | Purpose |
|---|---|
POST /predict | Run the model and wait for the complete result |
POST /predict/stream/ | Run the model and receive the result incrementally over SSE |
POST /predict/async/ | Queue the run and return its prediction_id immediately |
GET /predict/async/result/?request_id=<prediction_id> | Fetch the result of a queued run; POST here returns 405 Method Not Allowed |
POST /predict/cancel/ | Cancel a running prediction by its prediction_id |
GET /openapi.json | The model's own schema: exact inputs, types, and output fields |
Not every model supports every route. Text generation models are
streaming-only and reject /predict; see Using LLMs.
Retrying an async run safely
Send an Idempotency-Key header with POST /predict/async/ when a retry must
not start a second paid run. The key is 1-255 printable ASCII characters with no
leading or trailing spaces; use a new key for each run you intend.
curl -X POST https://api.flymy.ai/api/v1/flymyai/nano-banana/predict/async/ \
-H "X-API-KEY: fly-***" \
-H "Idempotency-Key: icon-run-7f3c2a" \
-F "prompt=A blue circle, flat icon"
- Same key, same input:
202with the first run'sprediction_id. Nothing runs or is charged again. - Same key, other input:
409withcode: idempotency_key_reused, before anything runs. - The first request is still being submitted:
409withcode: idempotency_key_in_flight. Send the same request again a moment later. - The first submission broke off after the run may have started:
409withcode: tool_outcome_unknown. The run may exist, so check your results before starting it again under a new key.
Without the header every request queues a new run. /predict and
/predict/stream/ do not keep keys. The Agents MCP run_model sends its
operation_key as this header for image and video models.
Discovering a model's inputs
Rather than guessing parameter names, read the schema the model publishes:
curl -H "X-API-KEY: fly-***" \
https://api.flymy.ai/api/v1/flymyai/google-gemini-25-flash/openapi.json
The input fields live under components.schemas.DynamicInputModel, and the
output fields under DynamicOutputModel. A field's description states its
limits when the model has them, such as allowed durations, file types or a
minimum video size. An output field marked
"isStream": true means the value is delivered progressively and the model
should be called through /predict/stream/.
Request format
Requests are sent as form data, not JSON - this is what allows file inputs such as images and audio to travel in the same request as text parameters.
curl -X POST \
https://api.flymy.ai/api/v1/flymyai/google-gemini-25-flash/predict/stream/ \
-H "X-API-KEY: fly-***" \
-F "prompt=Hello"
A JSON body returns 422 Field required even when the JSON itself is valid.
A list input goes as one field per item, and an object as its JSON text:
curl -X POST \
https://api.flymy.ai/api/v1/flymyai/gemini-3_8-flash-vlm/predict \
-H "X-API-KEY: fly-***" \
-F "prompt=How many photos show a dog?" \
-F "media_url=https://example.com/1.jpg" \
-F "media_url=https://example.com/2.jpg" \
-F 'response_schema={"type":"object","properties":{"count":{"type":"integer"}}}'
The Python SDK (flymyai 1.2.0rc10 and later) sends lists and objects this
way for you.
Response format
Synchronous
/predict returns a single JSON document with the model's outputs under
output_data.
Streaming
/predict/stream/ returns a Server-Sent Events stream. The first event
acknowledges the request and carries the prediction_id used for cancellation:
event: {"prediction_id":"f9e443caf50e..."}
Content events follow, each carrying a fragment of the output:
data: {"output_data":{"output":["first fragment "]},"status":200}
The stream closes with a final event whose output_data is empty and which
carries usage information. For token-priced models this is stream_details
with the token counts the charge is computed from:
data: {"output_data":{},"status":200,"stream_details":{"input_tokens":15,"output_tokens":49}}
Disable client-side buffering when consuming a stream, otherwise your HTTP
client may hold the fragments and hand you the whole response at the end. With
curl, pass -N.
Errors
Transport-level failures use standard HTTP status codes. Some conditions are
reported inside a 200 response body with their own status_code field, so
check the payload rather than the HTTP status alone:
{"detail":"Predict is not available for current pipeline. Use /predict/stream route instead!","status_code":421}
| Status | Meaning |
|---|---|
403 API key does not have access to the project | Model is private and you are not its owner |
403 Insufficient funds | Wallet balance is negative |
403 Project is not active | The project has no capacity allocated |
404 Project not found | The endpoint id does not exist |
422 Field required | A required parameter is missing, or the body was sent as JSON |
When a model refuses the request itself, the message stays in detail and,
if the model says why, reason comes next to it - for example a Vision prompt
over its 100,000-character limit:
{"output_data":{"detail":"Vision API returned HTTP 400","reason":"... String should have at most 100000 characters [string_too_long]"},"status":400}
Keep matching on the status and detail; reason is for people and logs, and
a refusal without one looks as before.
See Errors for the full list.
Related
- Using LLMs - text generation, streaming, token billing
- Queues - long-running and batched work
- Model usage data - per-request usage and price
- api.flymy.ai/docs - interactive OpenAPI reference
Typed decisions
For fast classification, routing, triage, fixed-enum extraction and yes/no gates, use TypeSafe Jev 1.13. It accepts state and typed questions through its JSON Decisions endpoint and returns Choice, Noul probability or Score answers. It is not a chat model and does not generate prose, code or media. Both MCP servers expose make_typed_decision; agents discover typesafe_jev.decide.