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.

Client gửi prompt→Hàng đợi→Acc Meta rảnh nhất→meta.ai vẽ→Ảnh lưu trên server, trả link

Base URL: {{BASE}} · Mọi request/response là JSON · Một job thường xong trong 10–60 giây.

Bắt đầu nhanh

01
Lấy API keyAdmin tạo key trong trang Quản trị → tab Test & API key.
02
Gửi promptChỉ cần prompt. Số ảnh, tỉ lệ, phong cách ghi luôn trong prompt.
03
Nhận ảnhThêm "wait": true để nhận ảnh ngay trong response, hoặc poll theo id.
curl
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
  }'
response
{
  "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.

Đủ thông tinTạo 4 ảnh chú chó corgi đội mũ phù thuỷ, tỉ lệ 9:16, phong cách tranh màu nước
Tiếng AnhImagine 2 images of a neon Tokyo street at night in the rain, 16:9, cinematic photo
Ngắnlogo con cú tối giản, nền trắng
Prompt chỉ mô tả, không nói "tạo ảnh"? Server tự thêm tiền tố 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

POST/v1/images/generationsXếp hàng tạo ảnh, trả về job
TrườngKiểuMô tả
promptbắt buộcstringMô tả ảnh, có thể kèm số ảnh / tỉ lệ / phong cách. Tối đa 4000 ký tự.
waittuỳ chọnbooleantrue = 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ọnstringWebhook: server POST đối tượng job tới URL này khi job xong hoặc lỗi.
response_formattuỳ chọnstringurl (mặc định) hoặc b64_json — kèm base64 của ảnh trong data[] (chỉ khi có ảnh).
modeltuỳ chọnstringmeta-imagine. Có thể gắn tỉ lệ vào tên: meta-imagine-16:9.
ntuỳ chọnintegerSố ảnh mong muốn (1–10). Ghép vào prompt và cắt bớt nếu Meta trả thừa.
ratiotuỳ chọnstringTỉ lệ W:H, ví dụ 16:9, 9:16, 1:1. Tên khác: aspect_ratio.
sizetuỳ chọnstringKiểu OpenAI, ví dụ 1792x1024 — tự đổi ra tỉ lệ gần nhất.
styletuỳ chọnstringPhong 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áchDùng khiLà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.
pollApp 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).
webhookNhiều job, không muốn giữ kết nốiGử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

GET/v1/images/generations/{id}Trạng thái + ảnh

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

GET/v1/images/generations/{id}/content/{index}File ảnh (cần key)

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ề.

Ảnh chỉ lưu trên server một thời gian (mặc định 7 ngày). Nên tải ảnh về hệ thống của bạn ngay khi job xong.

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:

python
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

POST/v1/chat/completionsCho client chỉ nói chuyện kiểu chat

Lấy tin nhắn user cuối cùng làm prompt, chờ tạo xong và trả ảnh dạng markdown ![image 1](url). 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ảng images.
  • stream: true — mở SSE ngay, gửi dòng giữ kết nối : keep-alive mỗ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
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"}]}'
response
{
  "id": "chatcmpl-6f1c0a9e…",
  "object": "chat.completion",
  "model": "meta-imagine",
  "choices": [{ "index": 0, "finish_reason": "stop",
    "message": { "role": "assistant", "content": "![image 1]({{BASE}}/media/…/0.jpg)\n![image 2](…)" } }],
  "images": [ { "index": 0, "url": "…", "width": 1024, "height": 1344 } ]
}

Models

GET/v1/modelsDanh sách model

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

GET/v1/usageHạn mức của key
{
  "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.

codeHTTPÝ 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_position cho 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_refused và meta.no_image là 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.