Webhooks
Register an HTTPS endpoint and AIVeed calls it when a job finishes — no polling. Two events:
job.completed and job.failed. Up to 5 active
webhooks per account, plus optional per-job webhooks (webhook_url + webhook_secret
on any generate request).
Register
bash
curl -X POST "https://api.aiveed.io/v1/webhooks" \
-H "X-API-Key: $AIVEED_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/aiveed/webhook", "events": ["job.completed", "job.failed"]}'If you do not supply a secret (16–64 chars), one is generated and returned once in the
response. URLs must be https and publicly routable — private, loopback, and cloud-metadata addresses are
rejected (422), and redirects are never followed.
Delivery envelope
json
{
"event": "job.completed",
"job": {
"id": "job_abc123",
"status": "completed",
"type": "video",
"model": "seedance-v1-pro",
"credits_charged": 30,
"result_url": "https://..."
}
}Verify the signature (required)
Every delivery is signed: X-AIVeed-Signature: t=<unix-seconds>,sha256=<hex>, where
<hex> = HMAC-SHA256(secret, t + "." + raw_body). Reject the delivery unless the
HMAC matches and t is within 300 seconds — the
timestamp bound is your replay protection.
Node.js
javascript
import crypto from 'node:crypto';
function verifyAiveedSignature(header, rawBody, secret) {
const [tPart, sigPart] = header.split(',');
const t = Number(tPart.slice(2));
const sig = sigPart.slice(7);
const expected = crypto.createHmac('sha256', secret)
.update(`${t}.${rawBody}`).digest('hex');
const fresh = Math.abs(Date.now() / 1000 - t) <= 300;
return fresh && sig.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}
// Express: app.post('/aiveed/webhook', express.raw({ type: '*/*' }), (req, res) => {
// if (!verifyAiveedSignature(req.get('X-AIVeed-Signature'), req.body.toString(), SECRET)) {
// return res.status(401).end();
// }
// const { event, job } = JSON.parse(req.body);
// res.status(200).end(); // ack fast, process async
// });Python
python
import hmac, hashlib, time
def verify_aiveed_signature(header: str, raw_body: bytes, secret: str) -> bool:
t_part, sig_part = header.split(',')
t = int(t_part[2:])
sig = sig_part[7:]
expected = hmac.new(secret.encode(), f'{t}.'.encode() + raw_body, hashlib.sha256).hexdigest()
fresh = abs(time.time() - t) <= 300
return fresh and hmac.compare_digest(sig, expected)Retries & failure handling
- Deliveries are at-least-once with retry backoff — dedupe on
(job.id, event). - Respond 2xx quickly; do the work asynchronously.
- An endpoint failing 10 consecutive deliveries is deactivated (visible on the dashboard and in
GET /v1/webhooks); delete and re-add it once fixed.