Documentation Rivya AI

Webhooks API

Créez des endpoints webhook API Rivya signés, vérifiez les signatures de livraison, inspectez les tentatives de livraison et envoyez des événements de test sûrs.

Dernière révision le 2026/05/11

Utilisez les webhooks API lorsque votre intégration a besoin que Rivya notifie votre serveur après qu'une génération Public API atteint un état terminal.

Le polling GET /api/v1/generations/{taskId} reste pris en charge. Les webhooks ajoutent des callbacks signés pour les systèmes de production qui préfèrent la livraison d'événements.

Scope requis

La gestion des webhooks nécessite une clé API avec :

webhooks:manage

Les nouvelles clés créées dans les paramètres incluent ce scope par défaut.

Créer un endpoint

POST /api/v1/webhooks
curl https://rivya.ai/api/v1/webhooks \
  -H "Authorization: Bearer rvya_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Webhook production",
    "url": "https://example.com/rivya/webhook",
    "event_types": ["generation.succeeded", "generation.failed"]
  }'

La réponse inclut signing_secret une seule fois :

{
  "id": "whend_...",
  "object": "webhook_endpoint",
  "name": "Webhook production",
  "url": "https://example.com/rivya/webhook",
  "event_types": ["generation.succeeded", "generation.failed"],
  "status": "active",
  "secret_preview": "whsec_12...abc123",
  "signing_secret": "whsec_...",
  "last_success_at": null,
  "last_failure_at": null,
  "failure_count": 0,
  "created_at": "2026-05-11T00:00:00.000Z",
  "updated_at": "2026-05-11T00:00:00.000Z",
  "disabled_at": null,
  "revoked_at": null
}

Stockez le secret complet sur votre serveur. Si vous le perdez, appelez l'endpoint de rotation et mettez à jour votre récepteur.

Règles d'URL

Les URL d'endpoint doivent être en HTTPS. Rivya rejette les URL avec identifiants, fragments, noms localhost, adresses de réseau local, plages IP privées, adresses de loopback et adresses réservées.

Rivya envoie toujours :

  • POST
  • Content-Type: application/json
  • aucun header de requête personnalisé contrôlé par l'utilisateur
  • aucun suivi automatique des redirections
  • un court délai d'expiration de livraison

Événements

Types d'événements actuels :

  • generation.succeeded
  • generation.failed

Les payloads webhook utilisent le même sérialiseur de génération public que l'endpoint de statut.

{
  "id": "evt_...",
  "type": "generation.succeeded",
  "api_version": "2026-05-11",
  "created_at": "2026-05-11T00:00:00.000Z",
  "data": {
    "generation": {
      "id": "task_public_id",
      "status": "succeeded",
      "model": "z-image",
      "reserved_credits": 1,
      "final_credits": 1,
      "created_at": "2026-05-11T00:00:00.000Z",
      "updated_at": "2026-05-11T00:01:00.000Z",
      "result": {
        "primary_url": "https://...",
        "urls": ["https://..."]
      },
      "error": null
    }
  }
}

Headers de livraison

Chaque livraison inclut :

Rivya-Webhook-Id: evt_...
Rivya-Webhook-Timestamp: 1778467200
Rivya-Webhook-Signature: v1=<hex-hmac-sha256>
Rivya-Webhook-Attempt: 1
Rivya-Webhook-Endpoint-Id: whend_...
Rivya-Request-Id: req_...

Entrée de signature :

${timestamp}.${rawBody}

Algorithme :

HMAC-SHA256 avec le secret de signature de l'endpoint

Rejetez les requêtes avec des timestamps périmés. Une tolérance de cinq minutes est un réglage pratique par défaut.

Vérification JavaScript

import crypto from "node:crypto";

function verifyRivyaWebhook({ rawBody, headers, signingSecret }) {
  const timestamp = headers["rivya-webhook-timestamp"];
  const signature = headers["rivya-webhook-signature"] || "";
  const actual = signature.split(",").find((part) => part.startsWith("v1="))?.slice(3);
  const expected = crypto
    .createHmac("sha256", signingSecret)
    .update(`${timestamp}.${rawBody}`)
    .digest("hex");

  if (!actual) return false;
  return crypto.timingSafeEqual(Buffer.from(actual, "hex"), Buffer.from(expected, "hex"));
}

Vérification Python

import hmac
import hashlib

def verify_rivya_webhook(raw_body: str, headers: dict, signing_secret: str) -> bool:
    timestamp = headers.get("rivya-webhook-timestamp", "")
    signature = headers.get("rivya-webhook-signature", "")
    actual = next((part[3:] for part in signature.split(",") if part.startswith("v1=")), "")
    expected = hmac.new(
        signing_secret.encode(),
        f"{timestamp}.{raw_body}".encode(),
        hashlib.sha256,
    ).hexdigest()
    return bool(actual) and hmac.compare_digest(actual, expected)

Gérer les endpoints

GET /api/v1/webhooks
GET /api/v1/webhooks/{endpointId}
PATCH /api/v1/webhooks/{endpointId}
DELETE /api/v1/webhooks/{endpointId}
POST /api/v1/webhooks/{endpointId}/rotate-secret
curl https://rivya.ai/api/v1/webhooks \
  -H "Authorization: Bearer rvya_sk_..."

curl https://rivya.ai/api/v1/webhooks/whend_... \
  -H "Authorization: Bearer rvya_sk_..."

curl -X PATCH https://rivya.ai/api/v1/webhooks/whend_... \
  -H "Authorization: Bearer rvya_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"status":"disabled"}'

curl -X POST https://rivya.ai/api/v1/webhooks/whend_.../rotate-secret \
  -H "Authorization: Bearer rvya_sk_..."

DELETE /api/v1/webhooks/{endpointId} désactive l'endpoint. Il ne supprime pas l'historique des livraisons.

Enregistrements de livraison

Lister les événements récents :

GET /api/v1/webhook-events
curl https://rivya.ai/api/v1/webhook-events \
  -H "Authorization: Bearer rvya_sk_..."

Lister les tentatives de livraison pour un endpoint :

GET /api/v1/webhooks/{endpointId}/deliveries
curl https://rivya.ai/api/v1/webhooks/whend_.../deliveries \
  -H "Authorization: Bearer rvya_sk_..."

Les enregistrements de livraison incluent le statut, le statut HTTP, le numéro de tentative, l'id de requête, la durée, un extrait tronqué de la réponse et les champs d'erreur publics.

Événement de test

Envoyez un payload de test sûr :

POST /api/v1/webhooks/{endpointId}/test
curl -X POST https://rivya.ai/api/v1/webhooks/whend_.../test \
  -H "Authorization: Bearer rvya_sk_..."

L'événement de test utilise webhook.test. Il ne crée pas de tâche de génération, ne consomme pas de crédits et n'inclut pas de véritable URL de résultat.

Politique de nouvelle tentative

Rivya traite HTTP 2xx comme un succès.

Les échecs incluent les erreurs réseau, les timeouts, les réponses de redirection et les réponses non-2xx. Rivya réessaie jusqu'à cinq tentatives :

  • immédiatement
  • après 1 minute
  • après 5 minutes
  • après 30 minutes
  • après 2 heures

Après la dernière tentative, l'événement est marqué failed.

Les échecs de livraison webhook ne changent pas le statut de génération, les crédits, les remboursements ni l'historique des tâches.

Checklist de sécurité

  • Vérifiez la signature HMAC avant d'analyser la logique métier.
  • Rejetez les timestamps périmés.
  • Traitez les événements de test séparément des événements de génération.
  • Ne loggez pas les secrets de signature complets.
  • Renvoyez 2xx uniquement après que votre récepteur a accepté l'événement.
  • Gardez le polling comme solution de secours pour la réconciliation.

Pages associées

Table des matières