Base URL

Recommended Base URL for the OpenAI-compatible API:

https://api.alice.fans/api/v1
The legacy URL https://api.alice.fans/v1 still works for existing clients; new integrations should use https://api.alice.fans/api/v1.
Authentication

Except for the public model list and model-pricing endpoints, inference endpoints require an API key in the request headers. Two headers are supported:

  • Recommended:Authorization: Bearer miyang-xxxxx
  • Fallback:x-api-key: miyang-xxxxx

Create API keys in the console; they are stored encrypted and can be viewed and copied again on the API Keys page.

bash
# Bearer Token(推荐)
curl https://api.alice.fans/api/v1/models \
  -H "Authorization: Bearer miyang-xxx"

# x-api-key(备用)
curl https://api.alice.fans/api/v1/models \
  -H "x-api-key: miyang-xxx"
Model naming

Model IDs usually follow {provider_slug}/{model_name}. Prefer miyang/auto to pick a model automatically, or copy another call ID from the model list or the console.

  • miyang/auto — Automatically pick a model for the current request
  • miyang/standard — Standard-tier model
  • miyang/premium — Premium-tier model

miyang/* models are for the Alice client; other apps or scripts should pick models whose usage_scope is general from the model list.

python
# 自动选择适合当前请求的模型
model = "miyang/auto"
Rate limits

Each API key is counted separately. The default is 60 requests/minute and you can raise the cap in the console. Exceeding the limit returns 429 Too Many Requests.

http
{
  "error": {
    "message": "Rate limit exceeded",
    "type": "rate_limit_error",
    "code": 1002
  }
}
Billing

Calls are settled against actual usage in real time. Refer to the console and the model-pricing response for current rates.

  • Checks that balance > 0 before the call; insufficient balance returns 402
  • Billed by prompt + completion token usage
  • Prompt Cache is supported: cache_read_tokens is billed at a discounted rate

Top up Jellybeans in the console and review calls and spend under Usage.

json
// 余额不足响应(402)
{
  "error": {
    "message": "Insufficient balance",
    "type": "insufficient_balance",
    "code": 1004
  }
}
Chat Completions
POST /api/v1/chat/completions

OpenAI-compatible chat endpoint with streaming and non-streaming output. Point the OpenAI SDK base_url here.

ParameterTypeDescription
model requiredstringModel ID, format provider_slug/model
messages requiredarrayChat messages; each item has role and content
streambooleanEnable streaming (SSE); default false
temperaturefloatSampling temperature, range 0–2
max_tokensintegerMaximum output tokens
response_formatobjectStructured output format; see Structured output
bash
curl https://api.alice.fans/api/v1/chat/completions \
  -H "Authorization: Bearer miyang-xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "miyang/auto",
    "messages": [
      {"role": "user", "content": "Hello!"}
    ],
    "stream": false
  }'
Omni v1

miyang/miyang-omni-v1 is an omni-modal model for audio/video understanding, meeting notes, and content analysis. A single user message may combine text, images, audio, and video, with text output.

Omni produces generative understanding suited to summaries, Q&A, and analysis. For a stable verbatim transcript, speaker diarization, and structured segments, use the file transcription model miyang-asr.
Model informationValue
Call IDmiyang/miyang-omni-v1
Input modalitiesText, image, audio, and video; inputs may be combined
Output modalityText (no speech generation)
Context limit1000000 tokens

Multimodal content format

typeDescription
textText instruction in the text field
image_urlPublic URL or Base64 data URL in image_url.url
input_audioPublic URL or Base64 data URL in input_audio.data, with format
video_urlPublic video URL or Base64 data URL in video_url.url

Omni extensions

ParameterTypeDescription
reasoning_effortstringnone, low, medium, or xhigh. Upstream defaults to xhigh; use none for transcription or quick summaries.
use_multichannelbooleanPreserve stereo or four-channel FOA spatial information; default false. Enable only when the input actually has a supported channel layout.

Audio understanding example

bash
curl https://api.alice.fans/api/v1/chat/completions \
  -H "Authorization: Bearer miyang-xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "miyang/miyang-omni-v1",
    "reasoning_effort": "none",
    "messages": [{
      "role": "user",
      "content": [
        {"type": "text", "text": "Transcribe this recording chronologically and summarize it."},
        {"type": "input_audio", "input_audio": {
          "data": "https://example.com/meeting.mp3",
          "format": "mp3"
        }}
      ]
    }],
    "stream": false
  }'
Public URL: each audio or video file must be no larger than 2 GB; audio is limited to 3 hours and video to 2 hours. A Base64-encoded audio or video file must be under 10 MB. Long media can take time, so raise the client timeout.
List models
GET /api/v1/models

Public endpoint, no API key required. Returns publicly available models; with an API key it also returns internal or allowlisted models for that account. The response extends the standard OpenAI shape with context_length and usage-scope fields.

json
{
  "object": "list",
  "data": [
    {
      "id": "miyang/auto",
      "object": "model",
      "owned_by": "miyang",
      "name": "自动",
      "model_type": "text",
      "usage_scope": "alice",
      "usage_hint": "请在 Alice 客户端内使用",
      "context_length": 262144
    }
  ]
}
Model pricing
GET /api/v1/pricing

Returns pricing for every model visible to the current account. Without an API key it lists public models; with one it also includes internal or allowlisted models permitted for that account.

Billing units vary by model type, so use billing_unit as the source of truth. rates contains the currently effective prices, while effective_pricing identifies base, time-based, or promotional pricing.

Each item carries its own currency; mili_per_usd provides the conversion between the USD balance and Jellybeans.
bash
curl https://api.alice.fans/api/v1/pricing \
  -H "Authorization: Bearer miyang-xxx"
json
{
  "object": "pricing.list",
  "mili_per_usd": 1000,
  "data": [
    {
      "id": "miyang/auto",
      "model_type": "text",
      "currency": "USD",
      "billing_mode": "tokens",
      "billing_unit": "per_1m_tokens",
      "effective_pricing": "<base | peak | promotion>",
      "rates": {
        "input": "<current rate>",
        "output": "<current rate>",
        "cache_read": "<current rate>",
        "cache_write": "<current rate>"
      }
    }
  ]
}
Embeddings
POST /api/v1/embeddings

OpenAI-compatible embeddings endpoint. Whether a model supports embedding tasks is marked on the model list and in the console.

ParameterTypeDescription
model requiredstringEmbedding model call ID
input requiredstring / arrayText or array of texts to embed
encoding_formatstringVector encoding format; commonly float
bash
curl https://api.alice.fans/api/v1/embeddings \
  -H "Authorization: Bearer miyang-xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "provider/embedding-model",
    "input": "需要向量化的文本"
  }'
Structured Decisions (Jev)
POST /api/v1/decisions

miyang/jev-1.13 is a low-cost structured decision model available to every Miyang API user and pinned to typesafe/jev-1.13. It answers explicit questions instead of generating chat text. Alice's long-term memory pre-filter is its first production use.

Any valid Miyang API key can call it with Authorization: Bearer miyang-xxx. It uses a dedicated Decisions protocol rather than /api/v1/chat/completions, so it is not mixed into the Chat-only /api/v1/models list.
Model informationValue
Miyang model IDmiyang/jev-1.13
Decision enginetypesafe/jev-1.13
Context limit32768 tokens
Question typesnoul / choice / score
AvailabilityAll users with a valid Miyang API key

Requests must name a registered Decisions shell. The Gateway bills that shell while pinning the real upstream engine. state holds structured context and questions defines the decisions to make.

ParameterTypeDescription
model requiredstringUse miyang/jev-1.13 for public calls. Ordinary API users cannot call internal scenario shells.
state requiredobjectStructured state used for the decision; callers should remove unnecessary sensitive data before sending.
questions requiredobjectObject keyed by question name; 1 to 24 questions.
questions.*.type requiredstringnoul (0–1 probability), choice, or score.
questions.*.instructions requiredstringA precise description of the decision to make.
questions.*.criteriaobjectOptional meaning for each answer or score, used to reduce ambiguity.

Each request is limited to 64 KiB and 24 questions. The server does not log state content or decision answers; only question count, latency, and token usage are retained.

bash
curl https://api.alice.fans/api/v1/decisions \
  -H "Authorization: Bearer miyang-xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "miyang/jev-1.13",
    "state": {"dialog": "The user asked a routine technical question"},
    "questions": {
      "remember": {
        "type": "noul",
        "instructions": "Does this conversation contain information worth retaining long term?",
        "criteria": {
          "true": "Stable identity, long-term preference, or an explicit relationship event",
          "false": "One-off task, routine Q&A, or small talk"
        }
      }
    }
  }'
json
{
  "model": "miyang/jev-1.13",
  "provider": "miyang",
  "answers": {
    "remember": {
      "type": "noul",
      "noul": 0.02
    }
  }
}
Images Generations (text-to-image)
POST /api/v1/images/generations

OpenAI-compatible image generation. Send a text prompt and get an image URL or Base64 data, fully compatible with the OpenAI Images API.

Image generation is slow (typically 30–120 seconds). Set the timeout in your SDK or HTTP client to at least 180 seconds.
ParameterTypeDescription
model requiredstringModel ID, format provider/model, e.g. ts/gpt-image-2
prompt requiredstringImage description
nintegerNumber of images; default 1, multiple allowed
sizestringImage size. Common values: 1024x1024 (square), 1024x1536 (portrait), 1536x1024 (landscape), auto (model chooses). Max edge 3840px; both sides must be multiples of 16; aspect ratio at most 3:1
qualitystringRender quality: low (fast draft), medium, high, auto (default, model chooses)
output_formatstringOutput format: png (default), jpeg (faster), webp
output_compressionintegerCompression 0–100; JPEG / WebP only
backgroundstringopaque (default) or transparent (transparent background, good for icons/stickers)
moderationstringModeration: auto (default) or low (lenient)

Basic example — text-to-image:

bash
curl https://api.alice.fans/api/v1/images/generations \
  -H "Authorization: Bearer miyang-xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "ts/gpt-image-2",
    "prompt": "A children'\''s book drawing of a veterinarian listening to the heartbeat of a baby otter",
    "size": "1024x1024",
    "quality": "high"
  }'
python
from openai import OpenAI
import base64

client = OpenAI(
    api_key="miyang-xxx",
    base_url="https://api.alice.fans/api/v1",
    timeout=180.0,  # 图像生成需要较长超时
)

result = client.images.generate(
    model="ts/gpt-image-2",
    prompt="A children's book drawing of a veterinarian listening to the heartbeat of a baby otter",
    size="1024x1024",
    quality="high",
)
print(result.data[0].url)

Advanced example — JPEG output + compression + save locally:

python
import httpx, json, base64

resp = httpx.post(
    "https://api.alice.fans/api/v1/images/generations",
    headers={"Authorization": "Bearer miyang-xxx"},
    json={
        "model": "ts/gpt-image-2",
        "prompt": "A serene Japanese garden with a koi pond",
        "size": "1536x1024",
        "quality": "medium",
        "output_format": "jpeg",       # jpeg 比 png 更快
        "output_compression": 80,     # 压缩率 0-100
    },
    timeout=180.0,
)
data = resp.json()
print(data["data"][0]["url"])
json
// 响应示例
{
  "created": 1779691963,
  "data": [
    {
      "url": "https://image.token-recyclebin.com/images/2026/05/25/xxx.png",
      "revised_prompt": "A serene Japanese garden with a koi pond..."
    }
  ]
}

Size and quality notes

ParameterValuesDescription
size1024x1024 (square)
1536x1024 (landscape)
1024x1536 (portrait)
2048x2048(2K)
3840x2160 (4K landscape)
auto
Max edge ≤ 3840px; both sides multiples of 16; ratio ≤ 3:1; total pixels 655,360 – 8,294,400
qualitylow · medium · high · autolow is fastest, good for drafts; high is most detailed, good for finals
output_formatpng · jpeg · webpjpeg is faster than png; prefer it when latency matters
Images Edits (reference / image-to-image)
POST /api/v1/images/edits

OpenAI-compatible image edits. Upload one or more reference images plus a text prompt to generate a new image. Supports inpainting (mask) and multi-image compose. Requests use multipart/form-data.

Typical uses:

  • Style transfer — Upload a photo + "turn into an oil painting"
  • Multi-image compose — Upload several assets + "make a gift basket with these items"
  • Inpainting — Upload the original + mask + "add a flamingo in the masked area"
ParameterTypeDescription
model requiredstringModel ID, e.g. ts/gpt-image-2
image requiredfile / file[]Reference image(s). One file as image; multiple as image[] (repeat image[]=@file.png)
prompt requiredstringEdit instruction
maskfileMask image (must include an alpha channel); transparent pixels are edited. With multiple images the mask applies to the first one
nintegerNumber of images; default 1
sizestringOutput size; default auto; same size options as Generations
qualitystringlow · medium · high · auto

Single-image edit — style transfer:

bash
curl https://api.alice.fans/api/v1/images/edits \
  -H "Authorization: Bearer miyang-xxx" \
  -F "model=ts/gpt-image-2" \
  -F "prompt=Turn this photo into a Studio Ghibli style illustration" \
  -F "image=@photo.png" \
  -F "size=1536x1024"
python
from openai import OpenAI

client = OpenAI(
    api_key="miyang-xxx",
    base_url="https://api.alice.fans/api/v1",
    timeout=180.0,
)

result = client.images.edit(
    model="ts/gpt-image-2",
    image=open("photo.png", "rb"),
    prompt="Turn this photo into a Studio Ghibli style illustration",
)
print(result.data[0].url)

Multi-image compose — merge several assets:

bash
# 多图参考:用 image[] 传多张
curl https://api.alice.fans/api/v1/images/edits \
  -H "Authorization: Bearer miyang-xxx" \
  -F "model=ts/gpt-image-2" \
  -F "image[]=@lotion.png" \
  -F "image[]=@soap.png" \
  -F "image[]=@candle.png" \
  -F 'prompt=A gift basket on a white background containing all these items'

Inpainting — use a mask:

python
# mask 需要有 alpha 通道,透明区域为编辑区
result = client.images.edit(
    model="ts/gpt-image-2",
    image=open("room.png", "rb"),
    mask=open("mask.png", "rb"),
    prompt="Add a flamingo in the pool area",
    quality="high",
)
print(result.data[0].url)
Mask requirements:The mask and source image must share size and format, each < 50MB. The mask must include an alpha channel (transparent pixels are edited). GPT Image treats the mask as prompt guidance and may not follow the edge exactly.
Ripple image restoration: create job
POST https://lab.miyang.cn/ripple/api/v1/jobs

Use this when a user needs to remove periodic artifacts—such as grid, scale, or roof-tile patterns—that build up as AI images are repeatedly used as references or regenerated. The service diagnoses, cleans, optionally regenerates, and quality-checks the source image in the background, returning a clean result ready to publish, print, or edit further.

Idempotency-Key is required. Reusing it after a network timeout returns the original job; reusing it with another image or parameter set returns 409.

Creation reserves Jellybeans for the maximum processing scope. Completion charges only the work actually performed and releases the remainder; failed jobs release the hold.
ParameterTypeDescription
image requiredfileImage to restore; PNG, JPEG, or WebP, up to 40 MB and 8.3 MP
allow_regenbooleanAllow regeneration when rule-based cleanup is insufficient; default true
max_regenintegerMaximum regeneration rounds, 1–2; default 2
bash
curl https://lab.miyang.cn/ripple/api/v1/jobs \
  -H "Authorization: Bearer miyang-xxx" \
  -H "Idempotency-Key: restore-order-001" \
  -F "image=@photo.png" \
  -F "allow_regen=true" \
  -F "max_regen=2"
json
{
  "id": "rp-api-...",
  "object": "ripple.job",
  "status": "queued",
  "phase": "queued",
  "result": null,
  "error": null
}
Ripple image restoration: query job
GET https://lab.miyang.cn/ripple/api/v1/jobs/{job_id}

Use this endpoint after creating a job to retrieve progress and the final artifacts. Asynchronous polling avoids holding a connection open or keeping the user waiting, and returns the finished artifact URL when the job succeeds.

status may be queued, processing, succeeded, failed, cancelled, or expired. On success, result.artifacts lists the final and process artifacts.

Artifact URLs also require the API key, so keep the Authorization header when downloading. Job files are retained for 24 hours; download them promptly or use the copies delivered to Miyang Drive.
bash
curl https://lab.miyang.cn/ripple/api/v1/jobs/rp-api-... \
  -H "Authorization: Bearer miyang-xxx"
json
{
  "id": "rp-api-...",
  "status": "succeeded",
  "result": {
    "outcome": "delivered",
    "regen_rounds": 1,
    "artifacts": [
      {
        "name": "photo_restored.png",
        "primary": true,
        "url": "https://lab.miyang.cn/ripple/api/v1/jobs/rp-api-.../artifacts/photo_restored.png"
      }
    ]
  },
  "error": null
}
Videos Generations
POST /api/v1/videos/generations

Asynchronous video generation. A successful request returns a task_id; poll the query endpoint for status instead of submitting the same business request again.

Currently available only to Alice and internal accounts. Supported models are miyang/h3 and miyang/h3-max.
ParameterTypeDescription
model requiredstringmiyang/h3 or miyang/h3-max
content requiredarrayMultimodal content array with exactly one non-empty text item; images, video, and audio may also be included
duration requiredintegerOutput duration in seconds. H3 supports 4–15; H3 Max supports 5–15
resolutionstringDefault 768P. H3 supports 768P / 2K; H3 Max supports 480P / 768P
ratiostringAspect ratio: 21:9, 16:9, 4:3, 1:1, 3:4, or 9:16; reference media may use adaptive
aigc_watermarkbooleanWhether to add an AIGC watermark
extraobjectH3 Max only. prompt_expansion_mode may be disabled, balanced, or quality

content media format

typeroleDescription
text—Required exactly once, up to 7,000 characters
image_urlfirst_frame / last_frame / reference_imageFirst frame, last frame, or reference image; one image without a role becomes the first frame
video_urlreference_videoReference video, up to 3; role is required
audio_urlreference_audioReference audio, up to 3; role is required
bash
curl https://api.alice.fans/api/v1/videos/generations \
  -H "Authorization: Bearer miyang-xxx" \
  -H "Idempotency-Key: alice-video-001" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "miyang/h3",
    "content": [
      {"type": "text", "text": "A lamb runs across a sunlit meadow"}
    ],
    "duration": 5,
    "resolution": "768P",
    "ratio": "16:9"
  }'
json
{
  "task_id": "443429054845209"
}
Query video task
GET /api/v1/videos/generations/{task_id}

Poll with the task_id returned at creation. Status may be queued, running, succeeded, failed, or cancelled. Poll every 5–15 seconds.

Successful videos are automatically copied to the current user's Miyang Drive and consume cloud quota. If storage is full, quota_full is returned; clean up files or expand storage before delivery and settlement can finish. Playback URLs are temporary signed URLs—query again when needed.
bash
curl https://api.alice.fans/api/v1/videos/generations/443429054845209 \
  -H "Authorization: Bearer miyang-xxx"
json
{
  "task": {
    "status": "succeeded",
    "resolution": "768P",
    "duration": 5,
    "content": {
      "url": "https://signed.example/video.mp4",
      "drive_file_id": "drv-xxx",
      "size_bytes": 1757278,
      "expires_in": 3600
    }
  }
}
Cancel video task
DELETE /api/v1/videos/generations/{task_id}

Cancel a task still being processed and release its billing hold. Any associated Miyang Drive file is also removed. For completed tasks that the upstream cannot cancel, follow the endpoint response.

bash
curl -X DELETE https://api.alice.fans/api/v1/videos/generations/443429054845209 \
  -H "Authorization: Bearer miyang-xxx"
File transcription (miyang-asr)
POST /api/v1/audio/transcriptions

Use miyang-asr to asynchronously transcribe a prerecorded audio or video file. It supports 30 languages and many Chinese dialects, and can identify speakers. Creation returns a task ID; query it for the transcript, segments, speakers, and duration.

Files uploaded with multipart/form-data are limited to 50 MB, saved automatically to the current user's Miyang Drive, and count toward storage. file_url accepts public HTTP(S) files up to 2 GB and 12 hours, and does not copy them to Drive.

The legacy model names miyang/transcription and miyang/transcription-realtime keep working and map automatically to miyang-asr and miyang-asr-realtime; existing code needs no changes.

ParameterTypeDescription
modelstringUse miyang-asr (or miyang/miyang-asr). This model is selected when omitted
filefileChoose either file or file_url. Supports mp3, wav, m4a, aac, flac, ogg, opus, mp4, mov, mkv, webm, and more; direct uploads are limited to 50 MB
file_urlstringChoose either file_url or file. Publicly reachable HTTP(S) URL whose hostname resolves to a public IP; up to 2 GB and 12 hours
source_languagestringDefaults to auto detection. Accepts cn, en, yue, ja, and ko; multilingual requires language_hints; fspk means mixed Chinese and English
language_hintsarray / stringAvailable only with source_language=multilingual; supports cn, en, yue, ja, ko, de, fr, and ru, up to 4
diarizationbooleanWhether to identify speakers; defaults to true. Audio under 2 hours is recommended when enabled
speaker_countintegerExpected number of speakers. Use 0 for automatic detection; otherwise 2–100

Billing uses the token usage reported by the upstream model, with audio input tokens and text output tokens priced separately. Refer to the console usage ledger for current pricing and final charges.

Creation places a Jellybean hold sized for 12 hours of audio. On completion, only actual usage is charged and the remainder is released. Failed tasks are not charged.

Example 1: upload a file and save it to Miyang Drive

bash
curl https://api.alice.fans/api/v1/audio/transcriptions \
  -H "Authorization: Bearer miyang-xxx" \
  -H "Idempotency-Key: meeting-20260921" \
  -F "model=miyang-asr" \
  -F "source_language=cn" \
  -F "diarization=true" \
  -F "file=@meeting.m4a"

Example 2: submit a public file URL (recommended for large files)

bash
curl https://api.alice.fans/api/v1/audio/transcriptions \
  -H "Authorization: Bearer miyang-xxx" \
  -H "Idempotency-Key: archive-001" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "miyang-asr",
    "file_url": "https://example.com/recording.mp3",
    "source_language": "multilingual",
    "language_hints": ["cn", "en"]
  }'
json
{
  "id": "6f3a...task",
  "object": "audio.transcription.job",
  "status": "processing",
  "model": "miyang/miyang-asr",
  "request_id": "3d7e...request",
  "source_file_id": "drv-..."
}
Query file transcription
GET /api/v1/audio/transcriptions/{task_id}

Query with the id returned at creation, typically every 5–15 seconds. If submission is uncertain, request_id can also locate the same task.

Status can be processing, completed, failed, or submission_uncertain. For submission_uncertain, keep querying with the original Idempotency-Key; do not submit again with a new key.
bash
curl https://api.alice.fans/api/v1/audio/transcriptions/6f3a...task \
  -H "Authorization: Bearer miyang-xxx"
json
{
  "id": "6f3a...task",
  "object": "audio.transcription.job",
  "status": "completed",
  "model": "miyang/miyang-asr",
  "text": "Meeting transcript...",
  "duration": 93.4,
  "segments": [
    {"speaker": "0", "start": 0.0, "end": 5.2, "text": "..."}
  ],
  "usage": {
    "audio_seconds": 93.4,
    "duration_ms": 93400,
    "input_tokens": 3270,
    "output_tokens": 412
  },
  "source_file_id": "drv-..."
}

Common errors:402 means insufficient Jellybeans; 409 means the idempotency key was reused for a different request; 411/413 means the upload lacks a length or exceeds 50 MB; 429 is rate limiting; 503 submission_uncertain means the upstream outcome is pending confirmation.

Realtime recognition (miyang-asr-realtime)
POST /api/v1/audio/transcriptions/realtime

Create a realtime record, then connect to the one-time stream_url. Clients may send PCM directly or common audio streams such as WAV, MP3, AAC, Ogg, WebM, and M4A. Miyang automatically decodes them into the optimal internal recognition format and returns unified recognition events, so clients never need to adapt to a specific recognition route.

Creation places a Jellybean hold based on max_duration_seconds. When the connection ends, billing uses the token usage reported upstream and releases the remainder. Lost connections are stopped automatically and repeated finalization cannot charge twice.
ParameterTypeDescription
modelstringUse miyang-asr-realtime (or miyang/miyang-asr-realtime). This model is selected when omitted
formatstringpcm / wav / mp3 / aac / opus / speex / ogg / webm / m4a / mp4
sample_rateinteger16000 is supported; 8000 is also supported for Chinese only
source_languagestringcn / en / yue / ja / ko / multilingual
language_hintsarrayAvailable only with source_language=multilingual; realtime recognition uses only the first hint
promptstringOptional recognition context, up to 400 characters. Use names, product names, meeting topics, domain terms, or immediately preceding text to improve accuracy. It does not change the response format and is not a general chat system prompt
output_levelinteger1 = final sentences only; 2 = interim and final results (default)
max_duration_secondsintegerMaximum duration of this realtime stream in seconds, from 1 to 86400. The Jellybean hold uses this limit; final billing uses actual usage

Format conventions: opus and speex use Ogg containers, aac uses ADTS, and m4a/mp4 use streamable fragmented MP4. WebM/Opus is recommended for browsers and M4A/AAC for Apple clients; Miyang handles decoding, mono conversion, and resampling.

Context enhancement examples

A prompt should state factual background likely to appear in the next audio segment, not ask the model to perform a task. The closer it matches the upcoming content, the more reliably names, products, and domain terms are recognized.

Use caseRecommended prompt
Names and proper nounsParticipants include Luo Xiaoshan and Eason. The product is Miyang and the project is Xingchao.
Meeting or class backgroundThis is a product weekly meeting about the screenshot cloud library, storage budgets, and the seven-day pending-deletion area.
Continue from prior contextThe previous segment discussed realtime speech recognition; next comes context enhancement and dynamic updates.
Change topics during a sessionThe next topic is the Xingchao release plan, led by Luo Xiaoshan.
State concise facts: who is involved, the project, important terms, and the current topic. Avoid vague commands such as “recognize accurately” or “make no mistakes.” Use context.update when the topic changes.
bash
curl https://api.alice.fans/api/v1/audio/transcriptions/realtime \
  -H "Authorization: Bearer miyang-xxx" \
  -H "Idempotency-Key: live-meeting-001" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "miyang-asr-realtime",
    "format": "pcm",
    "sample_rate": 16000,
    "source_language": "cn",
    "prompt": "这是一场米羊产品会议,参会人包括洛小山,项目名称是星潮计划。",
    "max_duration_seconds": 300,
    "output_level": 2
  }'
json
{
  "id": "realtime-task-id",
  "status": "ready",
  "mode": "realtime",
  "model": "miyang/miyang-asr-realtime",
  "stream_url": "wss://api.alice.fans/api/v1/audio/transcriptions/realtime/.../stream?token=...",
  "stream_token_expires_in": 600
}

stream_url expires in 10 minutes and can be connected only once; a successful connection means recognition has started. Keep sending audio bytes matching the creation parameters; Miyang handles format conversion and speech pauses automatically. To finish, send {"header":{"name":"StopTranscription"}}; the server delivers the final SentenceEnd and TranscriptionCompleted, then closes with 1000. You can also just close the connection. Afterwards, use the common query endpoint for the full transcript and settlement. Server events are JSON with these header.name values:

When the context changes, send {"type":"context.update","prompt":"接下来讨论星潮计划的发布安排。"} on the same WebSocket. The new prompt applies to subsequent audio, and Miyang returns ContextUpdated after accepting it.

javascript
// Update the context used for subsequent audio when the topic changes
ws.send(JSON.stringify({
  type: "context.update",
  prompt: "The next topic is the Xingchao release plan, led by Luo Xiaoshan."
}));

// Continue sending audio after receiving ContextUpdated
ws.send(nextAudioChunk);
EventDescription
SentenceBeginA sentence started; payload contains the sentence index and start time (ms)
TranscriptionResultChangedInterim result for the current sentence in payload.result; not sent when output_level=1
SentenceEndA sentence ended; payload contains the final result, begin_time, time, and per-word timings in words
ContextUpdatedMiyang accepted context.update; the new prompt applies to subsequent audio
ContextUpdateFailedcontext.update failed validation; payload.status_text explains why, and the client may retry with a corrected prompt
TranscriptionCompletedRecognition finished; the server closes the connection next
TaskFailedRecognition failed; header.status is 40000000 and payload.status_text gives the reason. The server then closes with 1011
json
{
  "header": {"namespace": "SpeechTranscriber", "name": "SentenceEnd", "status": 20000000},
  "payload": {
    "index": 1,
    "begin_time": 0,
    "time": 1820,
    "result": "今天的会议先同步进度。",
    "words": [{"text": "今天", "startTime": 0, "endTime": 320, "punctuation": ""}]
  }
}
Short-audio recognition
POST /api/v1/audio/transcriptions

Set model to miyang-asr-flash on the same transcription endpoint to get the text back directly, without an asynchronous task. Suited to audio under 5 minutes; use miyang-asr for longer recordings. The request body matches file transcription: choose either file or file_url.

Billed by the token usage reported upstream and charged immediately on success; failures are not charged.

bash
curl https://api.alice.fans/api/v1/audio/transcriptions \
  -H "Authorization: Bearer miyang-xxx" \
  -F "model=miyang-asr-flash" \
  -F "file=@voice-note.m4a"
json
{
  "text": "明天上午十点提醒我开会。",
  "model": "miyang/miyang-asr-flash",
  "usage": {"input_tokens": 125, "output_tokens": 9, "total_tokens": 134},
  "request_id": "3d7e...request"
}
Speech synthesis
POST /api/v1/audio/speech

Returns audio bytes synchronously with a Content-Type matching response_format. miyang-tts-v1 is optimized for realtime interaction and supports voices, pitch, and style instructions; miyang-tts-v1-pro is a unified audio generation model, currently exposed for single-speaker synthesis with optional reference audio.

ParameterTypeDescription
modelstringmiyang-tts-v1 or miyang-tts-v1-pro
inputstringText to synthesize (text is also accepted); up to 20000 characters for v1 and 3000 for v1 Pro
voicestringVoice ID, default longanhuan_v3.1; v1 only
response_formatstringmp3 (default), wav, pcm; v1 also supports opus
sample_rateinteger8000, 16000, 22050, 24000, 44100, 48000; v1 defaults to 24000, v1 Pro defaults to 48000 and does not support 22050
speednumberSpeaking rate 0.5–2, default 1
volumenumberVolume 0–100, default 50
pitchnumberPitch 0.5–2, default 1; v1 only
instructionstringNatural-language style instruction, up to 500 characters; v1 only
referencesarrayReference audio, up to 3 items, each with exactly one of audio_url or audio_data; v1 Pro only

Billed by the input and output tokens reported upstream; usage is also returned in the X-Usage-Input-Tokens and X-Usage-Output-Tokens response headers.

bash
curl https://api.alice.fans/api/v1/audio/speech \
  -H "Authorization: Bearer miyang-xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "miyang-tts-v1",
    "input": "欢迎使用米羊语音合成。",
    "voice": "longanhuan_v3.1",
    "response_format": "mp3"
  }' \
  --output speech.mp3
Realtime voice chat
WS /api/v1/realtime?model=miyang-omni-v1-realtime

miyang-omni-v1-realtime is a full-duplex voice conversation model. Connect over WebSocket and authenticate with the Authorization: Bearer miyang-xxx request header. Miyang transparently relays Realtime protocol client and server events (such as session.update, input_audio_buffer.append, response.create, and response.audio.delta).

A Jellybean hold is placed when the connection opens; billing uses the token usage reported upstream, with text tokens converted to equivalent audio tokens.

Rejected connections close with: 4401 authentication failed, 4402 insufficient Mili, 4403 model access denied, 4429 rate limited, 4503 route unavailable.

javascript
import WebSocket from "ws";

const ws = new WebSocket(
  "wss://api.alice.fans/api/v1/realtime?model=miyang-omni-v1-realtime",
  { headers: { Authorization: "Bearer miyang-xxx" } }
);
ws.on("open", () => {
  ws.send(JSON.stringify({
    type: "session.update",
    session: { modalities: ["text", "audio"] }
  }));
  // then send input_audio_buffer.append (Base64 PCM) and read response.audio.delta
});
ws.on("message", (data) => console.log(JSON.parse(data).type));
Web search (overview & billing)

Realtime web access for agents and apps: web search, news search, and page reading. All endpoints are GET and use the same API key as inference (Authorization: Bearer miyang-xxx).

Web-search calls are billable; refer to the console for current pricing.Failed requests (upstream errors, bad parameters, or no news results) are not charged.
EndpointParameterDescription
/api/v1/websearch/searchqDeep search: results include extracted page text and reranked context, good for RAG
/api/v1/websearch/simple-searchqQuick search: titles and snippets only, faster response
/api/v1/websearch/readerurlPage reader: fetch a URL and return clean text
/api/v1/websearch/search-newsqNews search: recent news sources only; results also include retrieval context
Quick search
GET /api/v1/websearch/simple-search

Search only—no extraction or reranking. Usually returns within 1 second. Use it when you only need title + snippet + link. If an answer card is hit, the response also includes answerBox.

ParameterTypeDescription
q requiredstringSearch query
bash
curl "https://api.alice.fans/api/v1/websearch/simple-search?q=最新AI新闻" \
  -H "Authorization: Bearer miyang-xxx"
json
// 响应示例
{
  "code": 200,
  "message": "ok",
  "took_ms": 950,
  "data": {
    "answerBox": {
      "title": "Latest AI news",
      "snippet": "..."
    },
    "organic": [
      {
        "title": "AI News",
        "link": "https://example.com",
        "snippet": "Latest updates..."
      }
    ]
  }
}
Page reader
GET /api/v1/websearch/reader

When you already have a page URL, fetch it and convert it to clean Markdown. This endpoint returns a top-level content field, not data.

ParameterTypeDescription
url requiredstringPage URL to read; must start with http:// or https://
bash
curl "https://api.alice.fans/api/v1/websearch/reader?url=https://go.dev" \
  -H "Authorization: Bearer miyang-xxx"
json
// 响应示例(content 为页面正文)
{
  "code": 200,
  "message": "ok",
  "content": "# The Go Programming Language\n\nGo is an open source programming language..."
}
News search
GET /api/v1/websearch/search-news

Searches recent news sources only. The rest of the pipeline matches deep search, and results also include contexts snippets.

No matching news returns 404 (body {"code": 404, "message": "no search results"}). That is a normal business result and is not charged.
ParameterTypeDescription
q requiredstringNews search query
bash
curl "https://api.alice.fans/api/v1/websearch/search-news?q=OpenAI" \
  -H "Authorization: Bearer miyang-xxx"
json
// 响应示例
{
  "code": 200,
  "message": "ok",
  "took_ms": 4200,
  "data": {
    "organic": [
      {
        "title": "Latest OpenAI news",
        "link": "https://example.com/news",
        "snippet": "Recent product and research updates...",
        "contexts": [
          { "idx": 0, "text": "..." }
        ]
      }
    ]
  }
}
Streaming (SSE)

Set "stream": true in the request body to stream. The response matches OpenAI's SSE spec. The stream ends with data: [DONE].

python
from openai import OpenAI

client = OpenAI(
    api_key="miyang-xxx",
    base_url="https://api.alice.fans/api/v1",
)

stream = client.chat.completions.create(
    model="miyang/auto",
    messages=[{"role": "user", "content": "Hello!"}],
    stream=True,
)

for chunk in stream:
    print(chunk.choices[0].delta.content, end="")
Structured output

response_format is passed through and supports JSON Schema. The upstream model enforces the format; the platform does not rewrite it.

json
{
  "model": "miyang/auto",
  "messages": [...],
  "response_format": {
    "type": "json_schema",
    "json_schema": {
      "name": "result",
      "schema": {
        "type": "object",
        "properties": {
          "answer": { "type": "string" }
        }
      }
    }
  }
}
Prompt Cache

For models that support Prompt Cache, cache-hit tokens from upstream are billed at a discount. The platform passes through the upstream usage field, and the invoice shows cache hits.

Field names differ by vendor:

  • cache_read_input_tokens — Anthropic
  • prompt_cache_hit_tokens — DeepSeek
  • cached_tokens — OpenAI
json
{
  "usage": {
    "prompt_tokens": 1000,
    "completion_tokens": 200,
    "cache_read_input_tokens": 800,   // Anthropic
    "prompt_cache_hit_tokens": 800,    // DeepSeek
    "cached_tokens": 800               // OpenAI
  }
}
Python SDK example

Swap base_url and api_key, then call through the OpenAI SDK.

python
from openai import OpenAI

client = OpenAI(
    api_key="miyang-xxx",
    base_url="https://api.alice.fans/api/v1",
)

resp = client.chat.completions.create(
    model="miyang/auto",
    messages=[{"role": "user", "content": "Hello!"}],
)
print(resp.choices[0].message.content)
cURL example

Verify an API key, connectivity, and request parameters without installing an SDK—ideal for a first integration or diagnosing request failures.

bash
# 非流式
curl https://api.alice.fans/api/v1/chat/completions \
  -H "Authorization: Bearer miyang-xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "miyang/auto",
    "messages": [{"role": "user", "content": "Hello"}]
  }'

# 流式
curl https://api.alice.fans/api/v1/chat/completions \
  -H "Authorization: Bearer miyang-xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "miyang/auto",
    "messages": [{"role": "user", "content": "Hello"}],
    "stream": true
  }'