Mimochi API
Connect your application to chat, image, and video models.
Quickstart
Use one Mimochi API key for text, image, and video generation. API requests use the same service-credit balance and holder eligibility as your Mimochi account.
Base URL: https://mimochi.si/v1
- Connect your wallet and create an API key.
- Enable
readplus the generation services your application needs. Set a lifetime budget, a per-request limit, and an optional expiry. - Store the key in your server environment. Add credits in Wallet & usage for paid models.
- Read the catalog, choose a model, and send a request with a unique idempotency key.
Set up your server environment
export MIMOCHI_API_KEY='YOUR_SERVER_API_KEY'
export MIMOCHI_BASE_URL='https://mimochi.si/v1'Do not expose your key in browser code, mobile app bundles, URLs, or public repositories. Requests are intended for your backend; browser cross-origin access is not supported.
Find a chat model
curl --fail-with-body "$MIMOCHI_BASE_URL/models?kind=chat" \
-H "Authorization: Bearer $MIMOCHI_API_KEY"Copy a model's full id into MIMOCHI_MODEL. IDs include their service prefix, such as chat:. The placeholder below must be replaced with an ID returned by your catalog.
export MIMOCHI_MODEL='chat:MODEL_ID_FROM_CATALOG'Make a text request
curl --fail-with-body "$MIMOCHI_BASE_URL/chat/completions" \
-H "Authorization: Bearer $MIMOCHI_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: welcome-chat-0001' \
--data "{\"model\":\"$MIMOCHI_MODEL\",\"messages\":[{\"role\":\"user\",\"content\":\"Write a short welcome message.\"}],\"max_tokens\":256,\"max_cost\":\"0.10\"}"max_cost is your credit reservation ceiling, not a price estimate. Choose a budget that fits the selected model and requested output. If it is too low, the request is rejected before generation. Change the idempotency key for a new generation; reuse it unchanged only when retrying the same request.
A completed request returns HTTP 200 with choices[0].message.content. A request still running after the connection window returns HTTP 202 with a job. Continue through that job's links.self; do not submit a new paid request.
Node.js · built-in fetch
// Node.js 22+. Set MIMOCHI_API_KEY and MIMOCHI_MODEL on your server.
import { randomUUID } from 'node:crypto';
const base = 'https://mimochi.si/v1';
const headers = {
Authorization: `Bearer ${process.env.MIMOCHI_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': randomUUID(),
};
const response = await fetch(`${base}/chat/completions`, {
method: 'POST', headers,
body: JSON.stringify({
model: process.env.MIMOCHI_MODEL,
messages: [{ role: 'user', content: 'Write a short welcome message.' }],
max_tokens: 256, max_cost: '0.10',
}),
});
const result = await response.json();
if (!response.ok) throw new Error(result.error?.message ?? `HTTP ${response.status}`);
if (response.status === 202) {
console.log('Continue with this job:', result.id, result.links.self);
} else {
console.log(result.choices[0].message.content);
console.log('Job for final billing:', result.mimochi.job_id);
}Keep the same idempotency key and request body if your request times out. A new UUID starts a different generation.
Python · standard library
# Set MIMOCHI_API_KEY and MIMOCHI_MODEL in the server environment.
import json
import os
import uuid
import urllib.request
import urllib.error
body = {
"model": os.environ["MIMOCHI_MODEL"],
"messages": [{"role": "user", "content": "Write a short welcome message."}],
"max_tokens": 256,
"max_cost": "0.10",
}
request = urllib.request.Request(
"https://mimochi.si/v1/chat/completions",
data=json.dumps(body).encode(),
headers={
"Authorization": "Bearer " + os.environ["MIMOCHI_API_KEY"],
"Content-Type": "application/json",
"Idempotency-Key": str(uuid.uuid4()),
},
method="POST",
)
try:
with urllib.request.urlopen(request, timeout=70) as response:
result = json.load(response)
if response.status == 202:
print("Continue with this job:", result["id"], result["links"]["self"])
else:
print(result["choices"][0]["message"]["content"])
print("Job for final billing:", result["mimochi"]["job_id"])
except urllib.error.HTTPError as error:
print("HTTP", error.code, error.read().decode())Keys & permissions
Every /v1 endpoint requires an API key in the request header:
Authorization: Bearer YOUR_SERVER_API_KEYCreate and revoke keys in API access after signing in with your wallet. The full secret is shown once; it cannot be retrieved later. A lost key should be revoked and replaced.
| Permission | Access |
|---|---|
read | Models, generation options, rates, job status and events, asset downloads, balance, and usage |
chat | Chat generation; cancellation also requires read |
image | Image generation and media uploads |
video | Video generation and media uploads |
For the full generation workflow, grant read together with the relevant service permission. An optional model allowlist restricts generation to specific catalog IDs. Leaving the list empty allows models within the key's service permissions.
Each key has a lifetime spending limit, a per-request limit, and a request rate limit. The default lifetime limit is 10 credits and the default per-request limit is 1 credit. A lifetime limit can be at most 1,000,000 credits; the per-request limit cannot exceed it. Requests per minute can be set from 1 to 120; the default is 60. Read requests and job polling also count toward this rate. Additional service limits apply: up to 6 chat submissions per key per minute, 12 job-event connections per key per minute, and 6 uploads per account per minute. Chat submissions (streaming and non-streaming) and job-event connections also share a combined limit of 12 connections per minute per account across all API keys. This account connection limit is checked before a new generation is accepted. Account-wide active-job limits also apply. At most 20 active keys can exist for one account. Use an expiry when access should end automatically.
Jobs, uploads, assets, and usage belong to the key that created them. Another key on the same account cannot retrieve those API resources. All keys share the account's service-credit balance, but each key has its own spending budget.
Revoking a key blocks new requests immediately. Existing generation jobs may still complete and settle against the account. Revoke and replace a key to change its permissions or limits; key editing is not available in this version.
The API accepts server-to-server requests. Do not send an Origin header or make API calls directly from a browser. Put your own authenticated application backend between your users and Mimochi.
Models & rates
Read model IDs and capabilities from the catalog instead of hard-coding model assumptions. Availability and supported configurations can change.
| Method | Endpoint | Purpose |
|---|---|---|
GET | /models | List models visible to this key |
GET | /models?kind=chat | Filter by chat, image, or video |
GET | /models/options?model=MODEL_ID | Supported parameters, defaults, and required media inputs |
GET | /models/rates?model=MODEL_ID | Published unit rates in credits |
curl --fail-with-body --get "$MIMOCHI_BASE_URL/models/options" \
-H "Authorization: Bearer $MIMOCHI_API_KEY" \
--data-urlencode "model=$MIMOCHI_MODEL"
curl --fail-with-body --get "$MIMOCHI_BASE_URL/models/rates" \
-H "Authorization: Bearer $MIMOCHI_API_KEY" \
--data-urlencode "model=$MIMOCHI_MODEL"The model list returns { "object": "list", "data": [...] }. Each entry includes its id, name, kind, available, context length, modalities, discount cap, and published pricing information. Chat input is text only. Catalog available describes platform availability (availability_scope: "platform"); it does not guarantee every API request is supported.
The options response uses API parameter names such as aspect_ratio, output_format, and generate_audio. Read parameters for permitted values and ranges, defaults for default values, inputs for media requirements, and prompt_required for whether a prompt is needed.
Check the options response's available, platform_available, and api_budget_support fields. An api_budget_support value of unsupported means the configuration cannot currently run through the API. A value of request_dependent requires validation of the actual request. Only send settings returned for the model. A model listed in the catalog may not support a particular combination of resolution, duration, reference inputs, or cost controls. API submission validates the exact request. api_budget_unsupported means that configuration cannot currently run with an enforceable API allowance; choose a different model or configuration.
The rates response contains model, currency: "credits", and lines. Each line contains its label, decimal amount, unit, and an optional note.
Published token rates are unit prices, not the cost of an entire request. Final billing uses verified actual usage. Holder discounts depend on your account's eligibility and the model's discount cap.
Chat & streaming
POST /chat/completions
Send the conversation history with every request. This is a text-only chat endpoint with familiar chat-completion request and response fields. It is a supported subset, not a claim that every option in another SDK is accepted.
| Field | Required | Description |
|---|---|---|
model | Yes | Full chat: model ID from the catalog |
messages | Yes | 1–100 messages with role and text content |
max_cost | Yes | Decimal string in credits, with up to six decimal places |
max_tokens | No | Integer from 1 to 65,536, subject to model support |
stream | No | false by default; true returns server-sent events |
Allowed roles are system, user, and assistant. The last message must be a user message. Each content string is non-empty and at most 8,000 characters; total content must be at most 48,000 UTF-8 bytes. The model's context limit also applies. The JSON request body must fit within 65,536 bytes. Unsupported fields are rejected rather than silently ignored.
This version does not accept images, videos, audio, files, tools, function calling, JSON schema output, or a temperature field in chat requests. Use the image and video endpoints for media generation.
Completion response
A completed response includes id, object: "chat.completion", model, choices, usage, and mimochi. Read the answer from choices[0].message.content. usage may be null while verified token counts are unavailable. mimochi.job_id and mimochi.status_url identify the saved job; check that job for final billing.
The connection waits for up to roughly 55 seconds. If the work has not finished, HTTP 202 returns a generation.job response with Location and Retry-After headers. The job continues after the response.
Streaming
curl --no-buffer --fail-with-body "$MIMOCHI_BASE_URL/chat/completions" \
-H "Authorization: Bearer $MIMOCHI_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: welcome-stream-0001' \
--data "{\"model\":\"$MIMOCHI_MODEL\",\"messages\":[{\"role\":\"user\",\"content\":\"Explain the idea in three short paragraphs.\"}],\"max_tokens\":512,\"max_cost\":\"0.10\",\"stream\":true}"Read data: JSON events and append choices[].delta.content. A completed stream sends a final choice, a usage chunk when verified counts are available, then data: [DONE]. Comment lines beginning with : are keepalives.
Named error and timeout events are not successful completion and do not send [DONE]. The event includes the existing job ID or status URL. Save the x-mimochi-job-id response header as soon as the connection opens. On timeout or disconnection, retrieve that job instead of creating a replacement generation.
Replaying a streaming request can resend already saved text. Reconstruct the message from the recovered job or replace the displayed content; do not blindly append a replay to an existing partial response. Closing the connection does not cancel the generation.
Image generation
POST /images/generations
Image generation is asynchronous. The response is HTTP 202 with a job ID, not an immediate list of public image URLs. Poll the saved job and download its assets once available.
Choose an image: model from the catalog, then read its options. Set MIMOCHI_IMAGE_MODEL to that exact ID.
export MIMOCHI_IMAGE_MODEL='image:MODEL_ID_FROM_CATALOG'
curl --fail-with-body "$MIMOCHI_BASE_URL/images/generations" \
-H "Authorization: Bearer $MIMOCHI_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: product-image-0001' \
--data "{\"model\":\"$MIMOCHI_IMAGE_MODEL\",\"prompt\":\"A ceramic cup photographed on a neutral studio background.\",\"max_cost\":\"1.00\",\"parameters\":{}}"The empty parameters object uses supported defaults. Add only the values published by /models/options: for example resolution, aspect_ratio, quality, output_format, or count when the chosen model supports them. Image count can be 1–4, subject to model limits.
For reference or editing workflows, upload the image first and place the returned upload ID in parameters.upload_ids. The selected model must explicitly support reference images. For example, the parameters shape is { "upload_ids": ["UPLOAD_ID"] }.
A model whose pricing cannot be bounded safely for an API request returns api_budget_unsupported. A published rate alone does not guarantee support for every API configuration. An image request may be available in the website while this API configuration is unavailable.
Video generation
POST /videos
Video generation is asynchronous. Submit once, save the returned job ID, and check the job's status. The video: model determines which text, image-reference, video-reference, or audio-reference workflows are supported.
export MIMOCHI_VIDEO_MODEL='video:MODEL_ID_FROM_CATALOG'
curl --fail-with-body "$MIMOCHI_BASE_URL/videos" \
-H "Authorization: Bearer $MIMOCHI_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: product-video-0001' \
--data "{\"model\":\"$MIMOCHI_VIDEO_MODEL\",\"prompt\":\"A slow camera move around a ceramic cup in soft studio light.\",\"max_cost\":\"1.00\",\"parameters\":{}}"This example uses defaults and a sample budget. Read model options first: a model may require references, and its selected configuration may need a higher budget. If prompt_required is false, send an empty prompt string when your workflow does not use one.
| Parameter | Use when supported |
|---|---|
duration | Requested output length in seconds |
resolution, aspect_ratio | Output dimensions or shape |
generate_audio | Generate audio along with the video |
upload_ids | Uploaded reference images; at most three, with model-specific limits |
reference_mode | reference or frames, according to the model |
source_video_id | Uploaded source video for editing or upscaling |
audio_upload_id | Uploaded speech/audio reference |
upscale_factor, creativity | Model-specific transformation controls |
The API validates media dimensions, duration, format, and the pricing of the selected configuration. Unsupported combinations are rejected before generation.
Poll jobs or use the job event stream to track progress. This version does not provide outgoing completion webhooks or video cancellation.
Uploads & downloads
Upload reference media with POST /uploads using multipart/form-data and exactly one file field. Use the same API key for uploading, generation, and downloading the results.
curl --fail-with-body "$MIMOCHI_BASE_URL/uploads" \
-H "Authorization: Bearer $MIMOCHI_API_KEY" \
-F 'file=@reference.png;type=image/png'The response includes the upload's id, verified media metadata, and expiry. Use its ID in upload_ids, source_video_id, or audio_upload_id, depending on the model. Read /models/options for accepted MIME types, file size limits, and required input counts. General limits are 10 MiB for reference images, 30 MB for audio, and 150 MB for video; a particular model can impose stricter limits.
Remote URLs and base64 media are not accepted as generation inputs. Upload actual media bytes. The API checks the file contents and model-specific requirements.
# Remove an input upload you no longer need.
curl --fail-with-body -X DELETE \
"$MIMOCHI_BASE_URL/uploads/UPLOAD_ID" \
-H "Authorization: Bearer $MIMOCHI_API_KEY"Deleting a reference can affect a request that has not finished using it. Wait for dependent jobs to finish before deleting it.
Completed media jobs contain output.assets. Each asset includes an id, mime_type, filename, expires_at, and content_url. These URLs require API authentication; they are not public links.
# Replace ASSET_ID with an ID from your completed job.
curl --fail-with-body "$MIMOCHI_BASE_URL/assets/ASSET_ID/content" \
-H "Authorization: Bearer $MIMOCHI_API_KEY" \
--output generated-media.binChoose a filename extension matching the asset's mime_type. Downloads support HTTP range requests for video. Retrieve media on your server and deliver it through your own application; never put a Mimochi API key in a public download URL.
Media is normally retained for 30 days. Treat each asset's expires_at as authoritative and save the files you need before they expire.
Jobs & recovery
Use the job ID returned by a generation request to recover progress, output, and final billing.
| Method | Endpoint | Purpose |
|---|---|---|
GET | /jobs/JOB_ID | Read status, output, assets, and billing |
GET | /jobs/JOB_ID/events | Server-sent snapshots of the saved job |
POST | /jobs/JOB_ID/cancel | Request cancellation of a chat job |
curl --fail-with-body "$MIMOCHI_BASE_URL/jobs/JOB_ID" \
-H "Authorization: Bearer $MIMOCHI_API_KEY"
curl --no-buffer --fail-with-body "$MIMOCHI_BASE_URL/jobs/JOB_ID/events" \
-H "Authorization: Bearer $MIMOCHI_API_KEY"A job response has object: "generation.job", id, kind, model, status, timestamps, output, usage, billing, error, and recovery links. Text appears in output.text; images and video appear in output.assets. output.expired indicates when retained output is no longer available. Billing records can remain after output expires. Replaying a completed chat after its retained text expires returns HTTP 410 with content_expired; it does not start a new generation. A stream reports the same condition as an error event without [DONE].
Typical progress is queued → submitting → running → storing → completed, although some services skip stages. failed and cancelled describe unsuccessful or cancelled generation. submission_unknown, needs_review, and storage_failed need verification or recovery; continue checking the existing job and avoid duplicate paid submissions.
Job events use event: snapshot with the full current job as data. Save each event's id and send it in Last-Event-ID when reconnecting to avoid receiving the same unchanged snapshot. This is a current-state stream, not a historical event log. Connections are bounded; reconnect or poll when they end. Poll every few seconds and slow down for long jobs, since polling counts against the key's rate limit.
Generation completion and billing settlement are separate. A completed output can still have pending billing. Check billing.status; billing.cost is null until the final customer charge is settled. If an administrator returns service credits, billing.cost becomes "0" and the response includes original_cost and refunded. billing.reserved is the remaining temporary hold, in credits.
# Chat only. Cancellation is best effort and does not erase incurred usage.
curl --fail-with-body -X POST \
"$MIMOCHI_BASE_URL/jobs/JOB_ID/cancel" \
-H "Authorization: Bearer $MIMOCHI_API_KEY"Closing a client connection does not cancel its job. Do not assume a failed HTTP connection means no generation was accepted.
Balance, usage & limits
GET /balance returns the shared account balance and the current key's budget information. GET /usage lists generation records created by the current key.
curl --fail-with-body "$MIMOCHI_BASE_URL/balance" \
-H "Authorization: Bearer $MIMOCHI_API_KEY"
curl --fail-with-body "$MIMOCHI_BASE_URL/usage?limit=20" \
-H "Authorization: Bearer $MIMOCHI_API_KEY"The balance response contains object: "balance", currency: "credits", and account available, reserved, and spent amounts. The nested api_key object contains id, spend_limit, spent, reserved, remaining, and per_request_limit. All amounts are decimal strings.
Usage returns { "object": "list", "data": [...], "has_more": false, "next_cursor": null }. Each record includes id, kind, model, status, created_at, verified token usage when available, and billing. The default page size is 25; limit accepts 1–100. When has_more is true, pass the exact next_cursor as the next request's cursor query parameter.
# Replace NEXT_CURSOR with the cursor from the previous response.
curl --fail-with-body --get "$MIMOCHI_BASE_URL/usage" \
-H "Authorization: Bearer $MIMOCHI_API_KEY" \
--data-urlencode 'limit=20' \
--data-urlencode 'cursor=NEXT_CURSOR'How a request uses credits
- Send a
max_costdecimal string with every generation request. It cannot exceed your key's per-request limit. - Mimochi checks the model and configuration, computes a conservative internal allowance, and validates the request budget, key lifetime budget, and available account credits.
- Accepted work reserves credits for that request. Other requests can use the remaining available balance, subject to their own limits.
- Verified actual usage determines the final charge. Eligible holder discounts apply, and unused held credits are released.
max_cost is a reservation ceiling and authorization limit. It is not a quote, a fee, or a promise that the generation will consume that amount. Lower max_tokens, shorten the input, or choose a less expensive configuration if a request cannot fit your budget. A configuration without enforceable cost controls is rejected.
The unit is credits: 1 credit = 1 USDG, with USD pricing accounted for at 1:1. No platform markup is added. A zero max_cost is accepted only for a verified free request. A key with zero lifetime and per-request budgets is limited to those free requests.
Your applied holder discount depends on current eligibility and the selected model's cap. For example, a verified cost of 0.10 credits with an applied 50% discount results in a 0.05 credit charge. The maximum advertised discount is not automatically the discount on every account or model.
The website and every API key share one balance. Key limits do not allocate extra credits. Reserved amounts count against available key budget until settlement. A lifetime limit does not reset each month. Existing jobs continue to settle if a key expires or is revoked.
Account balances do not become negative. If a verified charge exceeds the held amount, the discrepancy enters review rather than creating a negative user balance. Do not treat an unresolved or null charge as free usage.
Top-ups remain available through Wallet & usage. This developer API does not expose payment signing or a refund endpoint.
Idempotency & retries
Every generation submission requires an Idempotency-Key header. Use 8–128 letters, digits, hyphens, or underscores. A UUID is a suitable choice.
Reuse the same key and the same generation body after a timeout, a disconnected stream, or an uncertain HTTP response. Mimochi recovers the existing accepted job instead of starting another generation. Reusing the key with different generation data returns HTTP 409 with idempotency_conflict. Changing stream alone can recover the same generation using the other transport mode.
Save the idempotency key, original request body, and returned job ID in your application before retrying. A new idempotency key authorizes a new generation and can create an additional charge. Do not automatically retry a failed or uncertain generation with a fresh key.
For HTTP 429, wait for Retry-After when provided and back off between retries. For transient 5xx or network errors, use bounded exponential backoff and the original generation key. Once you know the job ID, status polling is preferable to repeated submissions. Do not retry 401, 403, 402, or validation errors without correcting their cause.
Idempotency applies to generation submissions. Uploads are separate resources; retrying a multipart upload can create a new upload ID. Reuse an existing upload when it has already been returned successfully.
Errors & endpoint reference
Errors use an error object with a code and human-readable message. Read error.request_id or the x-request-id response header for the request reference. Public API error codes use lowercase, such as api_budget_too_low. Never include your full API key when reporting an error.
| HTTP status | Meaning | Action |
|---|---|---|
401 | Missing, invalid, expired, or revoked key | Check authentication or replace the key |
402 | Insufficient credits or exhausted key budget | Add credits or create a key with an appropriate budget |
403 | Missing permission, disallowed model, or browser request | Check scopes, model allowlist, and backend use |
404 | Resource absent, expired, or unavailable to this key | Check the ID and the key that created it |
409 | Idempotency conflict or generation state conflict | Recover the original job and check its status |
410 | Previously generated chat output has expired | Use your saved output; a replay does not regenerate it |
413 | Payload or upload too large | Reduce request or file size |
415 | Unsupported content type | Use JSON or the documented multipart format |
422 | Invalid fields, unsupported configuration, or insufficient request allowance | Check model options and the error code |
429 | Rate limit reached | Back off; respect Retry-After when supplied |
5xx | Temporary service or infrastructure failure | Retry safely with the original idempotency key |
Useful budget codes include api_request_limit when max_cost exceeds the key's per-request limit, api_spend_limit when the key's lifetime budget is exhausted, api_budget_too_low when a configuration cannot fit the request allowance, and api_budget_unsupported when that configuration cannot be safely bounded for API use.
Full endpoint list
| Method | Endpoint | Permission |
|---|---|---|
GET | /models | read |
GET | /models/options | read |
GET | /models/rates | read |
POST | /chat/completions | chat |
POST | /images/generations | image |
POST | /videos | video |
POST | /uploads | image or video |
DELETE | /uploads/UPLOAD_ID | image or video |
GET | /jobs/JOB_ID | read |
GET | /jobs/JOB_ID/events | read |
POST | /jobs/JOB_ID/cancel | read + chat |
GET | /assets/ASSET_ID/content | read |
GET | /balance | read |
GET | /usage | read |
All paths above are relative to https://mimochi.si/v1. Generation permissions are necessary in addition to model eligibility and budget checks. Catalog entries do not override these checks.