meta2api — API tạo ảnh bằng Meta AI
Gửi một prompt, nhận về ảnh do Meta AI tạo. Phía sau là nhiều tài khoản meta.ai chạy trình duyệt headless, tự xoay vòng khi một tài khoản hết lượt hoặc lỗi.
Base URL: {{BASE}} · Mọi request/response là JSON · Một job thường xong trong 10–60 giây.
Bắt đầu nhanh
prompt. Số ảnh, tỉ lệ, phong cách ghi luôn trong prompt."wait": true để nhận ảnh ngay trong response, hoặc poll theo id.curl {{BASE}}/v1/images/generations \
-H "Authorization: Bearer $META2API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Tạo 4 ảnh chú mèo phi hành gia trên mặt trăng, tỉ lệ 16:9, phong cách anime",
"wait": true
}'{
"id": "6f1c0a9e2b8d4c55a0e3f7d2c1b4a987",
"object": "image.generation",
"status": "completed",
"model": "meta-imagine",
"prompt": "Tạo 4 ảnh chú mèo phi hành gia trên mặt trăng, tỉ lệ 16:9, phong cách anime",
"created": 1790489647,
"elapsed_s": 23.4,
"data": [
{ "index": 0, "url": "{{BASE}}/media/6f1c0a9e…/0.jpg", "width": 1344, "height": 756, "mime": "image/jpeg" },
{ "index": 1, "url": "{{BASE}}/media/6f1c0a9e…/1.jpg", "width": 1344, "height": 756, "mime": "image/jpeg" }
],
"reply_text": "Here are your images!",
"error": null
}Xác thực
Gửi key ở header Authorization: Bearer <key>. Cũng nhận X-API-Key: <key> hoặc query ?key=.
Mỗi key có thể có giới hạn lượt/ngày và tổng lượt. 1 lượt = 1 lần gọi tạo ảnh (dù Meta trả mấy ảnh). Lượt bị trừ khi tạo job và được hoàn lại nếu job lỗi — lỗi có "refunded": true.
Viết prompt
Viết như khi gõ trên meta.ai. Muốn bao nhiêu ảnh, tỉ lệ nào, phong cách gì thì ghi luôn vào prompt — tiếng Việt hay tiếng Anh đều được.
Imagine để Meta hiểu là cần vẽ. Nếu Meta vẫn chỉ trả lời bằng chữ, job tự thử lại một lần; vẫn không có ảnh thì lỗi meta.no_image (hoàn lượt).Các trường tuỳ chọn n, ratio, style (hoặc size kiểu OpenAI) chỉ là tiện ích: server ghép chúng vào cuối prompt, ví dụ … Number of images: 2. Aspect ratio: 16:9. Style: anime. Có n mà Meta trả nhiều ảnh hơn thì chỉ trả về n ảnh đầu.
Tạo job
| Trường | Kiểu | Mô tả |
|---|---|---|
promptbắt buộc | string | Mô tả ảnh, có thể kèm số ảnh / tỉ lệ / phong cách. Tối đa 4000 ký tự. |
waittuỳ chọn | boolean | true = giữ kết nối tới khi xong (tối đa ~300 giây) rồi trả luôn ảnh. Mặc định false. Cũng dùng được dạng query ?wait=true. |
callback_urltuỳ chọn | string | Webhook: server POST đối tượng job tới URL này khi job xong hoặc lỗi. |
response_formattuỳ chọn | string | url (mặc định) hoặc b64_json — kèm base64 của ảnh trong data[] (chỉ khi có ảnh). |
modeltuỳ chọn | string | meta-imagine. Có thể gắn tỉ lệ vào tên: meta-imagine-16:9. |
ntuỳ chọn | integer | Số ảnh mong muốn (1–10). Ghép vào prompt và cắt bớt nếu Meta trả thừa. |
ratiotuỳ chọn | string | Tỉ lệ W:H, ví dụ 16:9, 9:16, 1:1. Tên khác: aspect_ratio. |
sizetuỳ chọn | string | Kiểu OpenAI, ví dụ 1792x1024 — tự đổi ra tỉ lệ gần nhất. |
styletuỳ chọn | string | Phong cách, ví dụ anime, oil painting. |
Header Idempotency-Key: <chuỗi bất kỳ> tuỳ chọn: gửi lại cùng key trong 24 giờ sẽ nhận lại đúng job cũ thay vì tạo job mới — an toàn khi retry do mất mạng.
Response (không wait)
{
"id": "6f1c0a9e2b8d4c55a0e3f7d2c1b4a987",
"object": "image.generation",
"status": "queued",
"queue_position": 0,
"data": [],
"poll_url": "{{BASE}}/v1/images/generations/6f1c0a9e2b8d4c55a0e3f7d2c1b4a987",
"poll_after_s": 5,
…
}Chờ kết quả: poll · wait · webhook
| Cách | Dùng khi | Làm thế nào |
|---|---|---|
| wait | Đơn giản nhất, script / backend | "wait": true → response chứa luôn ảnh. Quá thời gian chờ thì trả HTTP 202 kèm job đang chạy, poll tiếp theo id. |
| poll | App có UI hiển thị tiến độ | Tạo job → gọi GET /v1/images/generations/{id} mỗi 3–5 giây, hoặc thêm ?wait=30 để server giữ tới 30 giây rồi mới trả (long-poll). |
| webhook | Nhiều job, không muốn giữ kết nối | Gửi callback_url. Body nhận được giống hệt response của GET; header X-Meta2api-Event: job.completed hoặc job.failed. Thử lại 3 lần nếu server bạn trả 5xx. |
Trạng thái job: queued → running → completed hoặc failed. Khi đang chạy có thêm phase: opening · sending · generating · downloading (và phase_text tiếng Việt để hiển thị).
Xem job
Query tuỳ chọn: wait=0…60 (long-poll, giây), response_format=b64_json. Chỉ xem được job do chính key đó tạo.
{
"id": "6f1c0a9e2b8d4c55a0e3f7d2c1b4a987",
"status": "running",
"phase": "generating",
"phase_text": "Meta đang vẽ",
"attempts": 1,
"data": [],
"error": null
}Job lỗi vẫn trả HTTP 200, lỗi nằm trong trường error:
{
"id": "…", "status": "failed", "data": [],
"reply_text": "Sorry, I can't create that image…",
"error": { "code": "meta.content_refused", "message": "…", "retryable": false, "refunded": true }
}Tải file ảnh
Link trong data[].url (/media/…) mở thẳng được, không cần key — dùng trực tiếp trong thẻ <img>. Endpoint content ở trên là bản cần key, trả kèm tên file để tải về.
Dùng thư viện OpenAI — images.generate
Endpoint tạo ảnh cùng dạng với OpenAI (created + data[].url), nên SDK OpenAI dùng được. Nhớ bật wait qua extra_body:
from openai import OpenAI
client = OpenAI(api_key="mk-…", base_url="{{BASE}}/v1")
res = client.images.generate(
model="meta-imagine",
prompt="Tạo 2 ảnh ngọn hải đăng lúc hoàng hôn, tỉ lệ 16:9, tranh sơn dầu",
extra_body={"wait": True},
timeout=320,
)
for img in res.data:
print(img.url)Lỗi trả về HTTP 4xx/5xx với body {"error": {…, "job_id"}} nên SDK ném exception như bình thường.
chat/completions
Lấy tin nhắn user cuối cùng làm prompt, chờ tạo xong và trả ảnh dạng markdown . Dùng được với các app chat hỗ trợ OpenAI (chọn model meta-imagine hoặc meta-imagine-16:9…).
stream: false— trảchat.completion, kèm thêm mảngimages.stream: true— mở SSE ngay, gửi dòng giữ kết nối: keep-alivemỗi 10 giây cho tới khi có ảnh, rồi gửi nội dung và[DONE]. Nên dùng stream nếu client/proxy có timeout ngắn.
curl {{BASE}}/v1/chat/completions \
-H "Authorization: Bearer $META2API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"meta-imagine","messages":[{"role":"user","content":"3 ảnh phố cổ Hội An về đêm, 3:4"}]}'{
"id": "chatcmpl-6f1c0a9e…",
"object": "chat.completion",
"model": "meta-imagine",
"choices": [{ "index": 0, "finish_reason": "stop",
"message": { "role": "assistant", "content": "\n" } }],
"images": [ { "index": 0, "url": "…", "width": 1024, "height": 1344 } ]
}Models
meta-imagine và các biến thể gắn tỉ lệ: meta-imagine-1:1, -16:9, -9:16, -4:3, -3:4, -3:2, -2:3, -21:9 — tiện cho client chỉ cho chọn model.
Lượt đã dùng
{
"label": "genvideo",
"used_today": 12, "daily_limit": 200, "remaining_today": 188,
"used_total": 530, "total_limit": null, "remaining_total": null,
"images_total": 1840, "pending_jobs": 1
}Mã lỗi
Mọi lỗi cùng một dạng: {"error": {"code", "message", "retryable", "refunded"}}. retryable: true nghĩa là gửi lại sau một lúc có thể thành công.
| code | HTTP | Ý nghĩa |
|---|
Code mẫu
import requests
BASE = "{{BASE}}"
KEY = "mk-…"
r = requests.post(f"{BASE}/v1/images/generations",
headers={"Authorization": f"Bearer {KEY}"},
json={"prompt": "Tạo 4 ảnh chú mèo phi hành gia, 16:9, anime", "wait": True},
timeout=330)
job = r.json()
if r.status_code >= 400:
raise RuntimeError(job["error"])
for img in job["data"]:
with open(f"meta_{img['index']}.jpg", "wb") as f:
f.write(requests.get(img["url"], timeout=60).content)const BASE = "{{BASE}}";
const KEY = "mk-…";
const res = await fetch(`${BASE}/v1/images/generations`, {
method: "POST",
headers: { "Authorization": `Bearer ${KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ prompt: "Tạo 2 ảnh logo cà phê tối giản, 1:1", wait: true }),
});
const job = await res.json();
if (!res.ok) throw new Error(job.error.message);
console.log(job.data.map(d => d.url));const BASE = "{{BASE}}";
const KEY = "mk-…";
const H = { "Authorization": `Bearer ${KEY}`, "Content-Type": "application/json" };
async function generate(prompt) {
let job = await (await fetch(`${BASE}/v1/images/generations`, {
method: "POST",
headers: { ...H, "Idempotency-Key": crypto.randomUUID() },
body: JSON.stringify({ prompt }),
})).json();
if (job.error && !job.id) throw new Error(job.error.message);
while (!["completed", "failed"].includes(job.status)) {
// long-poll: server giữ tối đa 30s, trả ngay khi job xong / lỗi
job = await (await fetch(`${BASE}/v1/images/generations/${job.id}?wait=30`, { headers: H })).json();
console.log(job.status, job.phase_text ?? "");
}
if (job.status === "failed") throw new Error(`${job.error.code}: ${job.error.message}`);
return job.data;
}
generate("Tạo 4 ảnh bãi biển nhiệt đới, 9:16, ảnh chụp film").then(console.log);<?php
$ch = curl_init("{{BASE}}/v1/images/generations");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 330,
CURLOPT_HTTPHEADER => ["Authorization: Bearer mk-…", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["prompt" => "Tạo 2 ảnh hoa sen, 3:4, tranh thuỷ mặc", "wait" => true]),
]);
$job = json_decode(curl_exec($ch), true);
foreach ($job["data"] ?? [] as $img) echo $img["url"], PHP_EOL;Lưu ý
- Thời gian: thường 10–60 giây/job. Job chờ khi mọi tài khoản đang bận;
queue_positioncho biết còn bao nhiêu job phía trước. - Tự thử lại: lỗi do tài khoản (bị đăng xuất, hết lượt, proxy chết, Meta chậm) được tự chuyển sang tài khoản khác, tối đa 3 lần — client không cần làm gì.
- Không thử lại:
meta.content_refusedvàmeta.no_imagelà do nội dung prompt — sửa prompt rồi gửi lại. - Số ảnh: Meta tự quyết số ảnh theo prompt (thường 1–4). Muốn chắc chắn tối đa bao nhiêu thì gửi thêm
n. - Giới hạn đồng thời: mỗi key có tối đa một số job chưa xong cùng lúc (mặc định 20) — vượt thì lỗi
quota.too_many_queued.