curl --request POST \
--url https://api.apiyi.com/v1/messages \
--header 'Content-Type: application/json' \
--header 'anthropic-version: <anthropic-version>' \
--header 'x-api-key: <api-key>' \
--data '
{
"model": "deepseek-v4-flash-vision-exp",
"max_tokens": 800,
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "What is in this image? Answer in one sentence."
},
{
"type": "image",
"source": {
"type": "url",
"url": "https://docs.apiyi.com/images/checks-passed.png"
}
}
]
}
]
}
'import requests
url = "https://api.apiyi.com/v1/messages"
payload = {
"model": "deepseek-v4-flash-vision-exp",
"max_tokens": 800,
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "What is in this image? Answer in one sentence."
},
{
"type": "image",
"source": {
"type": "url",
"url": "https://docs.apiyi.com/images/checks-passed.png"
}
}
]
}
]
}
headers = {
"anthropic-version": "<anthropic-version>",
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'anthropic-version': '<anthropic-version>',
'x-api-key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'deepseek-v4-flash-vision-exp',
max_tokens: 800,
messages: [
{
role: 'user',
content: [
{type: 'text', text: 'What is in this image? Answer in one sentence.'},
{
type: 'image',
source: {type: 'url', url: 'https://docs.apiyi.com/images/checks-passed.png'}
}
]
}
]
})
};
fetch('https://api.apiyi.com/v1/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.apiyi.com/v1/messages",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => 'deepseek-v4-flash-vision-exp',
'max_tokens' => 800,
'messages' => [
[
'role' => 'user',
'content' => [
[
'type' => 'text',
'text' => 'What is in this image? Answer in one sentence.'
],
[
'type' => 'image',
'source' => [
'type' => 'url',
'url' => 'https://docs.apiyi.com/images/checks-passed.png'
]
]
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"anthropic-version: <anthropic-version>",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.apiyi.com/v1/messages"
payload := strings.NewReader("{\n \"model\": \"deepseek-v4-flash-vision-exp\",\n \"max_tokens\": 800,\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"What is in this image? Answer in one sentence.\"\n },\n {\n \"type\": \"image\",\n \"source\": {\n \"type\": \"url\",\n \"url\": \"https://docs.apiyi.com/images/checks-passed.png\"\n }\n }\n ]\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("anthropic-version", "<anthropic-version>")
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.apiyi.com/v1/messages")
.header("anthropic-version", "<anthropic-version>")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"deepseek-v4-flash-vision-exp\",\n \"max_tokens\": 800,\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"What is in this image? Answer in one sentence.\"\n },\n {\n \"type\": \"image\",\n \"source\": {\n \"type\": \"url\",\n \"url\": \"https://docs.apiyi.com/images/checks-passed.png\"\n }\n }\n ]\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.apiyi.com/v1/messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["anthropic-version"] = '<anthropic-version>'
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"deepseek-v4-flash-vision-exp\",\n \"max_tokens\": 800,\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"What is in this image? Answer in one sentence.\"\n },\n {\n \"type\": \"image\",\n \"source\": {\n \"type\": \"url\",\n \"url\": \"https://docs.apiyi.com/images/checks-passed.png\"\n }\n }\n ]\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": "a5cb230d-ac08-43ed-8c4b-8f88b37119d3",
"type": "message",
"role": "assistant",
"model": "deepseek-v4-flash-vision-exp",
"content": [
{
"type": "text",
"text": "The image shows a notification stating that all checks have passed, including a successful Mintlify deployment."
}
],
"stop_reason": "end_turn",
"usage": {
"input_tokens": 295,
"output_tokens": 51,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>"
}
}DeepSeek V4 Flash Vision Messages API Reference
Anthropic-native /v1/messages API reference and playground for deepseek-v4-flash-vision-exp: base64 and URL image sources, thinking toggle, full tool round trip. Requires a ClaudeCode-group token.
curl --request POST \
--url https://api.apiyi.com/v1/messages \
--header 'Content-Type: application/json' \
--header 'anthropic-version: <anthropic-version>' \
--header 'x-api-key: <api-key>' \
--data '
{
"model": "deepseek-v4-flash-vision-exp",
"max_tokens": 800,
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "What is in this image? Answer in one sentence."
},
{
"type": "image",
"source": {
"type": "url",
"url": "https://docs.apiyi.com/images/checks-passed.png"
}
}
]
}
]
}
'import requests
url = "https://api.apiyi.com/v1/messages"
payload = {
"model": "deepseek-v4-flash-vision-exp",
"max_tokens": 800,
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "What is in this image? Answer in one sentence."
},
{
"type": "image",
"source": {
"type": "url",
"url": "https://docs.apiyi.com/images/checks-passed.png"
}
}
]
}
]
}
headers = {
"anthropic-version": "<anthropic-version>",
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'anthropic-version': '<anthropic-version>',
'x-api-key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'deepseek-v4-flash-vision-exp',
max_tokens: 800,
messages: [
{
role: 'user',
content: [
{type: 'text', text: 'What is in this image? Answer in one sentence.'},
{
type: 'image',
source: {type: 'url', url: 'https://docs.apiyi.com/images/checks-passed.png'}
}
]
}
]
})
};
fetch('https://api.apiyi.com/v1/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.apiyi.com/v1/messages",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => 'deepseek-v4-flash-vision-exp',
'max_tokens' => 800,
'messages' => [
[
'role' => 'user',
'content' => [
[
'type' => 'text',
'text' => 'What is in this image? Answer in one sentence.'
],
[
'type' => 'image',
'source' => [
'type' => 'url',
'url' => 'https://docs.apiyi.com/images/checks-passed.png'
]
]
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"anthropic-version: <anthropic-version>",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.apiyi.com/v1/messages"
payload := strings.NewReader("{\n \"model\": \"deepseek-v4-flash-vision-exp\",\n \"max_tokens\": 800,\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"What is in this image? Answer in one sentence.\"\n },\n {\n \"type\": \"image\",\n \"source\": {\n \"type\": \"url\",\n \"url\": \"https://docs.apiyi.com/images/checks-passed.png\"\n }\n }\n ]\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("anthropic-version", "<anthropic-version>")
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.apiyi.com/v1/messages")
.header("anthropic-version", "<anthropic-version>")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"deepseek-v4-flash-vision-exp\",\n \"max_tokens\": 800,\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"What is in this image? Answer in one sentence.\"\n },\n {\n \"type\": \"image\",\n \"source\": {\n \"type\": \"url\",\n \"url\": \"https://docs.apiyi.com/images/checks-passed.png\"\n }\n }\n ]\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.apiyi.com/v1/messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["anthropic-version"] = '<anthropic-version>'
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"deepseek-v4-flash-vision-exp\",\n \"max_tokens\": 800,\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"What is in this image? Answer in one sentence.\"\n },\n {\n \"type\": \"image\",\n \"source\": {\n \"type\": \"url\",\n \"url\": \"https://docs.apiyi.com/images/checks-passed.png\"\n }\n }\n ]\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": "a5cb230d-ac08-43ed-8c4b-8f88b37119d3",
"type": "message",
"role": "assistant",
"model": "deepseek-v4-flash-vision-exp",
"content": [
{
"type": "text",
"text": "The image shows a notification stating that all checks have passed, including a successful Mintlify deployment."
}
],
"stop_reason": "end_turn",
"usage": {
"input_tokens": 295,
"output_tokens": 51,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>"
}
}ClaudeCode group. This is a hard requirement.Using the default group hits two stacked problems:- Omitting
top_preturns 400Invalid top_p valueevery time - Even with
top_psupplied, replaying the first turn’sthinkingblock into the second turn returnsunknown variant 'thinking', expected one of 'text', 'image_url', 'file'—— and standard clients such as Claude Code and the Anthropic SDK always replay it, so multi-turn always breaks
ClaudeCode group and neither problem exists. For the OpenAI format use the
Chat Playground instead.sk-your-apiyi-key in x-api-key
(a ClaudeCode token, with no Bearer prefix) and leave anthropic-version at 2023-06-01.
The example uses a public image and has thinking disabled, so you can hit send and see a
response immediately.Parameter quick reference
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
model | string | ✓ | — | Always deepseek-v4-flash-vision-exp |
max_tokens | int | ✓ | — | Required in the Anthropic format, hard ceiling 393,216; use 2000+ with thinking on |
messages | array | ✓ | — | content is a string, or an array of content blocks |
system | string | — | System prompt | |
thinking.type | string | enabled | disabled leaves only a text block in content | |
thinking.budget_tokens | int | — | Thinking budget when enabled | |
stream | bool | false | SSE streaming with the standard Anthropic event sequence | |
top_p | number | — | Optional in the ClaudeCode group | |
temperature / top_k / stop_sequences | — | — | All effective | |
tools | array | — | Standard Anthropic input_schema format |
Two ways to send an image
source.type = "base64"
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/jpeg",
"data": "<BASE64>"
}
}
data carries no data:image/jpeg;base64, prefix —— this differs from the
OpenAI format.
source.type = "url"
{
"type": "image",
"source": {"type": "url", "url": "https://example.com/image.jpg"}
}
source.type = "url" works only in the ClaudeCode group; the default group returns
You have uploaded an unsupported image.source.type = "file" needs the Files API, which this platform does not offer.The response content is a block array
| Case | content |
|---|---|
| Default (thinking on) | [{"type": "thinking", ...}, {"type": "text", ...}] |
thinking.type = "disabled" | [{"type": "text", ...}] |
| When calling a tool | [{"type": "thinking", ...}, {"type": "tool_use", ...}] |
ClaudeCode group the thinking block carries a signature field, and streaming emits
signature_delta as well.
Multi-turn and the tool round trip
Put the previous assistant turn’s entirecontent back into messages —— including the
thinking block, do not strip it —— then append the tool_result:
{
"model": "deepseek-v4-flash-vision-exp",
"max_tokens": 1500,
"tools": [{
"name": "record_shape",
"input_schema": {
"type": "object",
"properties": {
"shape": {"type": "string"},
"color": {"type": "string"}
},
"required": ["shape", "color"]
}
}],
"messages": [
{"role": "user", "content": [
{"type": "text", "text": "Look at the image and call record_shape."},
{"type": "image", "source": {"type": "url", "url": "https://example.com/shape.jpg"}}
]},
{"role": "assistant", "content": "<the content array returned by the previous turn, verbatim>"},
{"role": "user", "content": [
{"type": "tool_result", "tool_use_id": "<the tool_use id from the previous turn>", "content": "{\"ok\":true}"}
]}
]
}
default group returns 400,
and it is the path every Claude Code style client takes —— which is why the group must be right.
How the cache fields read
Automatic prefix caching applies, mapped onto the standard Anthropic fields:| Field | Behaviour |
|---|---|
cache_read_input_tokens | Automatic prefix cache hit size. The hit stops before the first image; images themselves are never cached |
cache_creation_input_tokens | Always 0. Upstream uses automatic prefix caching and ignores explicit cache_control markers |
input_tokens | After a hit this holds only the uncached remainder, unlike the OpenAI format’s prompt_tokens which is always the full count. The two cannot be reconciled directly |
Common errors
| Error | Cause |
|---|---|
Invalid top_p value, the valid range of top_p is (0, 1.0] | A default group token without top_p —— switch to ClaudeCode |
unknown variant 'thinking' | A default group token replaying a thinking block —— switch to ClaudeCode |
You have uploaded an unsupported image | Unsupported format, or a default group token with source.type = "url" |
Image in assistant message is unsupported | Images may only appear in user messages |
image file size exceeds limit 32 MB | The image is larger than 32 MiB |
Authorizations
Your APIYI token, the raw sk- key. The token must be in the ClaudeCode group
Headers
Anthropic API version, always 2023-06-01
Body
Model ID, always deepseek-v4-flash-vision-exp
deepseek-v4-flash-vision-exp Output token budget (required in the Anthropic format), hard ceiling 393,216. Use 2000 or more with thinking on
x <= 393216Message array. content is either a plain string or an array of content blocks for mixed text and images
Show child attributes
Show child attributes
System prompt
Thinking toggle. With {"type": "disabled"} the response content holds only a text block. Works in both groups on this endpoint
Show child attributes
Show child attributes
Stream the response over SSE, emitting the standard Anthropic message_start / content_block_delta / message_stop events
Sampling temperature
Nucleus sampling threshold. Optional in the ClaudeCode group; in the default group, omitting it returns 400
Candidate cutoff
Stop sequences
Tool list in the standard Anthropic input_schema format. Verified with streaming increments and a full two-turn round trip
Response
Generation succeeded
Array of content blocks. [thinking, text] with thinking on, just [text] with it off, and [thinking, tool_use] when calling a tool
Usage. Note this differs from the OpenAI format: after a cache hit input_tokens holds only the uncached remainder, so it cannot be reconciled with prompt_tokens directly
Show child attributes
Show child attributes
Was this page helpful?