animal-gif API
Pricing: see the model page https://modelfold.ai/models/animal-gif
API キーでタスクを送信し、結果をポーリングまたはコールバックで受信します。詳細な生成パラメータは英語版を参照してください。
POST /api/tools/animal-gif/prepare · GET /api/tools/animal-gif/tasks/:id
Authorization: Bearer <API_KEY>
Idempotency-Key: 1–150 characters.
コールバック通知
JSON の最上位に次の項目を追加します。ファイルを直接アップロードする場合はクエリパラメータに指定します。API キーによるリクエストのみ対応し、Web 画面からの生成は購読しません。
| パラメータ | 説明 |
|---|---|
| callBackUrl | 任意。公開 HTTPS、ポート 443。認証情報・フラグメントは禁止。DNS の全アドレスが公開 IP である必要があります。配信ごとに再検証し接続先 IP を固定します。リダイレクトは禁止です。 |
| callbackSecret | callBackUrl を指定する場合は必須。独立したランダムな 32–256 文字の署名用秘密値。暗号化保存し、応答には含めません。API キーを使わないでください。 |
送信例
curl
curl 'https://modelfold.ai/api/tools/animal-gif/prepare' \
-H "Authorization: Bearer $MODELFOLD_API_KEY" \
-H 'Idempotency-Key: gif-callback-order-001' \
-H 'Content-Type: application/json' \
-d '{
"image_url": "https://example.com/animal.jpg",
"prompt": "walks naturally",
"transparent": false,
"callBackUrl": "https://your-service.example/webhooks/modelfold",
"callbackSecret": "replace-with-your-own-random-secret-at-least-32-characters"
}'Python
import os, requests
payload = {'image_url': 'https://example.com/animal.jpg', 'prompt': 'walks naturally', 'transparent': False, 'callBackUrl': 'https://your-service.example/webhooks/modelfold', 'callbackSecret': 'replace-with-your-own-random-secret-at-least-32-characters'}
payload["callbackSecret"] = os.environ["MODELFOLD_CALLBACK_SECRET"]
response = requests.post("https://modelfold.ai/api/tools/animal-gif/prepare",
headers={"Authorization": "Bearer " + os.environ["MODELFOLD_API_KEY"], "Idempotency-Key": "gif-callback-order-001"},
json=payload, timeout=180)
response.raise_for_status()
print(response.json())JavaScript (Node.js 18+)
const payload = {
"image_url": "https://example.com/animal.jpg",
"prompt": "walks naturally",
"transparent": false,
"callBackUrl": "https://your-service.example/webhooks/modelfold",
"callbackSecret": "replace-with-your-own-random-secret-at-least-32-characters"
}
payload.callbackSecret = process.env.MODELFOLD_CALLBACK_SECRET
const response = await fetch('https://modelfold.ai/api/tools/animal-gif/prepare', {
method: 'POST', headers: { Authorization: `Bearer ${process.env.MODELFOLD_API_KEY}`,
'Content-Type': 'application/json', 'Idempotency-Key': 'gif-callback-order-001' },
body: JSON.stringify(payload)
})
if (!response.ok) throw new Error(await response.text())
console.log(await response.json())POST body
POST 本文はポーリング応答と同じ構造で、精算完了時のスナップショットです。callback はキュー登録時の値です。最新の配信状態はポーリングで確認します。イベント ID は本文ではなくヘッダーにあります。
{
"code": 200,
"data": {
"taskId": "ecf94083-6e5c-4b3c-b0d1-554d38b3dc20",
"model": "modelfold/animal-gif",
"state": "success",
"status": "success",
"progress": null,
"resultJson": "{\"resultUrls\":[\"https://modelfold.ai/uploads/outputs/result.gif\"]}",
"failMsg": null,
"usage": {
"settled": true
},
"callback": {
"state": "pending",
"attempts": 0
}
}
}署名検証(Node.js / Express)
- X-ModelFold-Event-Id
- X-ModelFold-Timestamp: Unix seconds
- X-ModelFold-Signature: Base64(HMAC-SHA256(secret, timestamp + "." + eventId + "." + rawRequestBody))
import express from 'express'
import crypto from 'node:crypto'
const app = express()
// Register before express.json(); verify the original bytes.
app.post('/webhooks/modelfold', express.raw({type:'application/json',limit:'1mb'}), async (req,res) => {
const timestamp = req.get('X-ModelFold-Timestamp') || ''
const eventId = req.get('X-ModelFold-Event-Id') || ''
const received = Buffer.from(req.get('X-ModelFold-Signature') || '', 'base64')
const expected = crypto.createHmac('sha256', process.env.MODELFOLD_CALLBACK_SECRET)
.update(`${timestamp}.${eventId}.`).update(req.body).digest()
const valid = /^\d+$/.test(timestamp) && Math.abs(Date.now()/1000-Number(timestamp)) <= 300
&& eventId && received.length === expected.length && crypto.timingSafeEqual(received,expected)
if (!valid) return res.sendStatus(403)
const result = JSON.parse(req.body.toString('utf8'))
// Implement with your database: UNIQUE(eventId), durable insert before 2xx.
// Duplicate eventId: acknowledge without processing business logic again.
await persistEventOnce(eventId, result)
res.sendStatus(204)
})
app.listen(3000)Response fields and retries
Amount fields are omitted from examples. credits, estimatedCredits and usage.credits are numeric response fields; read their values from the API. usage.settled identifies the final result. On HTTP 409, read the latest response and update expectedCredits before retrying.
Endpoint: GET /api/tools/animal-gif/quote
