Documentation de l'API

API REST en JSON pour découper des extraits MP3 dans vos archives, et retrouver le bon moment à découper. Incluse à partir du plan Essentiel.

Démarrage rapide

L'API se trouve à https://piges.qoniqfx.com/api/v1. Elle fait ce que vous faites dans le lecteur : choisir un flux, une plage horaire, et obtenir un MP3. Trois appels suffisent.

  1. Créez une clé dans l'espace client, Gestion → API, puis gardez-la dans une variable d'environnement :

    bash
    export QONIQ_API_KEY="qp_live_…"
  2. Demandez la découpe.

    bash
    curl -X POST https://piges.qoniqfx.com/api/v1/extracts \
      -H "Authorization: Bearer $QONIQ_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
    "streamId": "3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
    "from": "2026-09-28T07:00:00+02:00",
    "to":   "2026-09-28T09:00:00+02:00",
    "name": "Matinale du 28/09"
      }'

    La réponse (201 Created) contient l'id de l'extrait, au statut queued.

  3. Quelques secondes plus tard, téléchargez le MP3. Tant qu'il n'est pas prêt, la route répond 409 : réessayez un peu plus tard.

    bash
    curl -L -o matinale.mp3 \
      -H "Authorization: Bearer $QONIQ_API_KEY" \
      https://piges.qoniqfx.com/api/v1/extracts/<id>/audio

Authentification

Chaque appel porte la clé dans l'en-tête Authorization :

http
Authorization: Bearer qp_live_…
  • Une clé appartient à la personne qui l'a créée et agit avec son rôle dans l'organisation, relu à chaque appel. Elle cesse de fonctionner si cette personne quitte l'organisation.
  • Deux niveaux d'accès : Lecture seule (flux, extraits, recherche) ou Lecture et découpe d'extraits (création et suppression en plus).
  • L'API ne permet pas d'administrer l'organisation : ni flux, ni équipe, ni abonnement, ni veille.
  • Utilisez la clé côté serveur uniquement (script, automate, serveur). L'API n'accepte pas les appels depuis un navigateur : une clé placée dans une page web serait lisible par tous.
  • Une clé compromise se révoque dans l'espace client, Gestion → API ; elle est refusée dès l'appel suivant.

Dates, pagination, idempotence

Dates. Toutes les dates sont au format ISO 8601. Indiquez toujours le fuseau : 2026-09-28T07:00:00+02:00 (heure de Paris en été, +01:00 en hiver) ou 2026-09-28T05:00:00Z (UTC). Les réponses sont en UTC.

Pagination. GET /extracts renvoie hasMore et nextStartingAfter. Pour la page suivante, repassez cette valeur dans le paramètre startingAfter.

bash
curl -H "Authorization: Bearer $QONIQ_API_KEY" \
  "https://piges.qoniqfx.com/api/v1/extracts?limit=100&startingAfter=8b0e7a52-6f1d-4c3a-9d2e-5b7c1a0f9e34"

Idempotence. Un script qui plante et recommence ne doit pas découper deux fois la même émission. Envoyez un en-tête Idempotency-Key avec POST /extracts : une même clé ne crée qu'un seul extrait, et les appels suivants renvoient celui-ci (200 et l'en-tête Idempotent-Replayed: true). Construisez-la à partir de ce que vous découpez, par exemple matinale-2026-09-28.

Erreurs et limites

Une erreur renvoie un code HTTP et un corps JSON, avec un message en français que vous pouvez afficher tel quel :

json
{
  "error": {
"code": "invalid_request",
"message": "Plage hors de la période d'archive."
  }
}
Codes
400invalid_requestParamètre manquant ou invalide, dates hors archive, extrait trop long. invalid_json si le corps n'est pas du JSON.
401invalid_api_keyClé absente, invalide ou révoquée.
403plan_requiredVotre plan n'inclut pas l'API.
403insufficient_scopeClé en lecture seule utilisée pour créer ou supprimer.
403quota_exceededQuota mensuel d'extraits atteint.
403forbiddenUn membre ne peut supprimer que ses propres extraits.
404not_foundFlux ou extrait introuvable dans votre organisation.
409extract_not_readyLe MP3 est encore en préparation. extract_failed si la préparation a échoué.
429rate_limitedTrop d'appels : attendez le nombre de secondes indiqué par l'en-tête Retry-After.
500internal_errorErreur de notre côté : réessayez, et contactez le support si elle persiste.
  • 120 appels par minute et par clé.
  • Un extrait dure au plus 3 h (24 h avec le plan Réseau) et doit tenir dans la fenêtre d'archive du flux (archiveWindow dans GET /streams/{id}).
  • Les extraits comptent dans le quota mensuel de vos plans, comme ceux créés depuis le lecteur.
  • Les extraits sont conservés même après l'expiration des archives, jusqu'à leur suppression.

Cycle de vie d'un extrait

queued→processing→readyoufailed
  • queued : la demande est enregistrée. processing : le MP3 est en cours d'assemblage à partir des archives.
  • ready : downloadUrl pointe directement sur le MP3. Ce lien expire après 60 minutes (downloadUrlExpiresAt) ; relisez l'extrait pour en obtenir un nouveau, ou passez par /audio.
  • failed : error explique pourquoi (par exemple, aucun enregistrement sur la plage à cause d'une coupure).
  • Comptez quelques secondes pour une heure d'antenne. Interrogez le statut toutes les 5 à 10 secondes, pas plus souvent.

Référence des routes

Adresse de base : https://piges.qoniqfx.com/api/v1. Les corps de requête et de réponse sont en JSON (Content-Type: application/json).

POST/extracts

Découper un extrait

Crée un extrait MP3 sur une plage d'un flux. Répond 201 avec l'extrait au statut queued (ou 200 s'il existait déjà pour cette Idempotency-Key). Clé « Lecture et découpe » requise.

Corps JSON
streamIdrequisuuidFlux à découper (propre ou suivi en veille), voir GET /streams.
fromrequisdate ISODébut de l'extrait.
torequisdate ISOFin de l'extrait, 3 h max après le début (24 h avec Réseau).
nametexteNom de l'extrait et du fichier MP3, 120 caractères max. Défaut : « Extrait ».
sharebooléentrue pour créer en plus un lien de partage public, valable 30 jours.
En-têtes
Idempotency-KeytexteFacultatif, 200 caractères max. Voir Dates, pagination, idempotence.
bash
curl -X POST https://piges.qoniqfx.com/api/v1/extracts \
  -H "Authorization: Bearer $QONIQ_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: matinale-2026-09-28" \
  -d '{"streamId":"3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f","from":"2026-09-28T07:00:00+02:00","to":"2026-09-28T09:00:00+02:00","name":"Matinale du 28/09","share":true}'
GET/extracts/{id}

Statut d'un extrait

Renvoie l'extrait. Quand status vaut ready, downloadUrl donne le MP3.

json
{
  "id": "8b0e7a52-6f1d-4c3a-9d2e-5b7c1a0f9e34",
  "streamId": "3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
  "streamName": "Ma Radio",
  "name": "Matinale du 28/09",
  "status": "ready",
  "from": "2026-09-28T05:00:00.000Z",
  "to": "2026-09-28T07:00:00.000Z",
  "durationSeconds": 7200,
  "sizeBytes": 115204096,
  "error": null,
  "downloadUrl": "https://piges.qoniqfx.com/api/media/…",
  "downloadUrlExpiresAt": "2026-09-28T10:12:44.000Z",
  "shareUrl": "https://piges.qoniqfx.com/e/…",
  "shareExpiresAt": "2026-10-28T09:12:40.000Z",
  "createdAt": "2026-09-28T09:12:40.000Z"
}
GET/extracts/{id}/audio

Télécharger le MP3

Redirige (302) vers le fichier MP3. Suivez la redirection (curl -L, ou l'option équivalente de votre bibliothèque HTTP). Répond 409 tant que l'extrait n'est pas prêt.

GET/extracts

Lister les extraits

Extraits de l'organisation, du plus récent au plus ancien, qu'ils aient été créés par l'API ou depuis le lecteur.

Paramètres
limitentier1 à 100, défaut 20.
streamIduuidSeulement les extraits de ce flux.
statustextequeued, processing, ready ou failed.
startingAfteruuidCurseur de pagination : nextStartingAfter de la page précédente.
json
{
  "data": [ { "id": "8b0e7a52-…", "status": "ready", … } ],
  "hasMore": true,
  "nextStartingAfter": "8b0e7a52-6f1d-4c3a-9d2e-5b7c1a0f9e34"
}
DELETE/extracts/{id}

Supprimer un extrait

Supprime l'extrait et son MP3 ; son lien de partage cesse de fonctionner. Répond 204. Un membre ne supprime que les extraits qu'il a créés, un administrateur tous ceux de l'organisation.

GET/streams

Lister les flux

Vos flux et les radios suivies en veille (watched: true), avec l'état de la captation et le titre en cours.

json
{
  "data": [
{
  "id": "3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
  "name": "Ma Radio",
  "status": "active",
  "shared": false,
  "watched": false,
  "label": null,
  "recorderState": "recording",
  "recorderError": null,
  "lastSegmentAt": "2026-09-28T09:12:30.000Z",
  "currentTitle": "ARTISTE - Titre"
}
  ]
}
GET/streams/{id}

Détail d'un flux

Ajoute la durée d'archive (retentionDays), la plage découpable (archiveWindow.from → archiveWindow.to) et l'incident en cours éventuel.

GET/titrage

Rechercher dans le titrage

Chaque passage d'un titre ou d'une pub annoncé par vos flux et vos radios de veille (métadonnées Icecast/Shoutcast), avec son heure de début et de fin. Pratique pour découper exactement une pub ou un titre.

Paramètres
qrequistexteTexte recherché.
streamIduuidLimiter à un flux.
periodetexte24h, 7j, 30j ou tout (défaut).
limitentier1 à 300, défaut 50.
json
{
  "data": [
{
  "streamId": "3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
  "streamName": "Ma Radio",
  "title": "PUB - Garage Martin",
  "startedAt": "2026-09-28T06:42:10.000Z",
  "endedAt": "2026-09-28T06:42:40.000Z"
}
  ]
}
GET/incidents

Coupures et blancs antenne

Incidents récents (gap : coupure, silence : blanc antenne). Une plage qui chevauche une coupure donne un extrait plus court, ou en échec si rien n'a été enregistré. Paramètres : streamId, limit (1 à 200).

GET/usage

Quotas de l'organisation

Flux et veille utilisés et disponibles, durée d'archive, options incluses dans vos plans.

Recettes

Découper la matinale chaque matin. Un script lancé par cron à 9 h 05, du lundi au vendredi (5 9 * * 1-5). La clé d'idempotence évite un doublon si le script est relancé.

bash
#!/usr/bin/env bash
set -euo pipefail
API="https://piges.qoniqfx.com/api/v1"
DAY=$(date +%F)
TZ_OFFSET=$(TZ=Europe/Paris date +%:z)

ID=$(curl -sf -X POST "$API/extracts" \
  -H "Authorization: Bearer $QONIQ_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: matinale-$DAY" \
  -d "{\"streamId\":\"3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f\",\"from\":\"${DAY}T07:00:00${TZ_OFFSET}\",\"to\":\"${DAY}T09:00:00${TZ_OFFSET}\",\"name\":\"Matinale ${DAY}\"}" \
  | jq -r .id)

# Attend que le MP3 soit prêt, puis le télécharge.
until curl -sf -L -o "matinale-$DAY.mp3" \
  -H "Authorization: Bearer $QONIQ_API_KEY" "$API/extracts/$ID/audio"; do
  sleep 10
done

Python, avec requests :

python
import os, time, requests

API = "https://piges.qoniqfx.com/api/v1"
session = requests.Session()
session.headers["Authorization"] = f"Bearer {os.environ['QONIQ_API_KEY']}"

r = session.post(f"{API}/extracts", json={
"streamId": "3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
"from": "2026-09-28T07:00:00+02:00",
"to": "2026-09-28T09:00:00+02:00",
"name": "Matinale du 28/09",
}, headers={"Idempotency-Key": "matinale-2026-09-28"})
r.raise_for_status()
extract = r.json()

while extract["status"] in ("queued", "processing"):
time.sleep(10)
extract = session.get(f"{API}/extracts/{extract['id']}").json()

if extract["status"] == "failed":
raise SystemExit(extract["error"])

with open("matinale.mp3", "wb") as f:
f.write(requests.get(extract["downloadUrl"]).content)

Node.js (18 et plus, sans dépendance) :

javascript
const API = "https://piges.qoniqfx.com/api/v1";
const headers = { Authorization: `Bearer ${process.env.QONIQ_API_KEY}` };

const res = await fetch(`${API}/extracts`, {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json", "Idempotency-Key": "matinale-2026-09-28" },
  body: JSON.stringify({
streamId: "3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
from: "2026-09-28T07:00:00+02:00",
to: "2026-09-28T09:00:00+02:00",
name: "Matinale du 28/09",
  }),
});
if (!res.ok) throw new Error((await res.json()).error.message);
let extract = await res.json();

while (extract.status === "queued" || extract.status === "processing") {
  await new Promise((r) => setTimeout(r, 10_000));
  extract = await (await fetch(`${API}/extracts/${extract.id}`, { headers })).json();
}
console.log(extract.status === "ready" ? extract.downloadUrl : extract.error);

Découper chaque passage d'une pub. Cherchez-la dans le titrage, puis découpez chaque passage trouvé, avec quelques secondes de marge :

bash
curl -s -G "https://piges.qoniqfx.com/api/v1/titrage" \
  -H "Authorization: Bearer $QONIQ_API_KEY" \
  --data-urlencode "q=Garage Martin" -d periode=24h \
| jq -c '.data[] | select(.endedAt != null)' | while read -r p; do
  FROM=$(date -u -d "$(jq -r .startedAt <<<"$p") - 2 seconds" +%FT%TZ)
  TO=$(date -u -d "$(jq -r .endedAt <<<"$p") + 2 seconds" +%FT%TZ)
  curl -s -X POST "https://piges.qoniqfx.com/api/v1/extracts" \
-H "Authorization: Bearer $QONIQ_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: pub-$(jq -r '.streamId + "-" + .startedAt' <<<"$p")" \
-d "$(jq -c '{streamId, from: $f, to: $t, name: .title}' --arg f "$FROM" --arg t "$TO" <<<"$p")"
done

n8n, Make, Zapier. Utilisez le module « HTTP Request » avec une authentification par en-tête (Authorization = Bearer qp_live_…), ou importez directement la spécification OpenAPI ci-dessous.

OpenAPI

La spécification OpenAPI 3.1 décrit toutes les routes, paramètres et réponses. Importez-la dans Postman, Insomnia, n8n ou un générateur de client. Téléchargez-la ci-dessous, ou appelez GET /openapi.json.