Skip to content

animal-gif API ​

Pricing: see the model page https://modelfold.ai/models/animal-gif

Envía una tarea con tu API Key y recibe el resultado mediante consulta o callback. Consulta la versión inglesa para todos los parámetros de generación.

English reference

POST /api/tools/animal-gif/prepare · GET /api/tools/animal-gif/tasks/:id

Authorization: Bearer <API_KEY>

Idempotency-Key: 1–150 characters.

Notificaciones por callback ​

Añade estos campos al nivel superior del JSON, o como parámetros de consulta al subir un archivo binario. Solo las solicitudes con API Key admiten callbacks; las generaciones desde la web no se suscriben.

ParámetroDescripción
callBackUrlOpcional. URL HTTPS pública en el puerto 443, sin credenciales ni fragmentos. Todas las direcciones DNS deben ser públicas. Cada intento vuelve a validar DNS y fija la IP de conexión. No se permiten redirecciones.
callbackSecretObligatorio con callBackUrl. Secreto aleatorio independiente de 32–256 caracteres, almacenado cifrado y nunca devuelto. No uses tu API Key.

Ejemplos de envío ​

curl ​

bash
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 ​

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+) ​

js
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 ​

El cuerpo POST tiene la misma estructura que la respuesta de consulta: una instantánea después de la liquidación. callback refleja el momento de encolado; consulta el estado actual de entrega. El ID del evento está en la cabecera, no en el cuerpo.

json
{
  "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
    }
  }
}

Verificación de firma (Node.js / Express) ​

  • X-ModelFold-Event-Id
  • X-ModelFold-Timestamp: Unix seconds
  • X-ModelFold-Signature: Base64(HMAC-SHA256(secret, timestamp + "." + eventId + "." + rawRequestBody))
js
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)

Devuelve cualquier 2xx en 10 segundos. Los errores de red, tiempos de espera y respuestas no 2xx se reintentan hasta 10 veces en total, con espera exponencial desde 30 segundos hasta una hora. No se siguen redirecciones. El ID y el cuerpo permanecen iguales; cambian la marca de tiempo y la firma. El estado persiste tras reinicios y el éxito confirmado detiene los intentos. Una confirmación perdida puede causar duplicados: deduplica de forma persistente por ID. callback.state es none / pending / delivered / exhausted y callback.attempts cuenta los intentos. Los fallos de entrega no cambian resultados ni cargos.

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

ModelFold — 一个 API,接入所有主流 AI 模型。