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.
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.
Créez une clé dans l'espace client, Gestion → API, puis gardez-la dans une variable d'environnement :
export QONIQ_API_KEY="qp_live_…"
Demandez la découpe.
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.
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.
curl -L -o matinale.mp3 \ -H "Authorization: Bearer $QONIQ_API_KEY" \ https://piges.qoniqfx.com/api/v1/extracts/<id>/audio
Chaque appel porte la clé dans l'en-tête Authorization :
Authorization: Bearer qp_live_…
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.
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.
Une erreur renvoie un code HTTP et un corps JSON, avec un message en français que vous pouvez afficher tel quel :
{
"error": {
"code": "invalid_request",
"message": "Plage hors de la période d'archive."
}
}| 400 | invalid_request | Paramètre manquant ou invalide, dates hors archive, extrait trop long. invalid_json si le corps n'est pas du JSON. |
| 401 | invalid_api_key | Clé absente, invalide ou révoquée. |
| 403 | plan_required | Votre plan n'inclut pas l'API. |
| 403 | insufficient_scope | Clé en lecture seule utilisée pour créer ou supprimer. |
| 403 | quota_exceeded | Quota mensuel d'extraits atteint. |
| 403 | forbidden | Un membre ne peut supprimer que ses propres extraits. |
| 404 | not_found | Flux ou extrait introuvable dans votre organisation. |
| 409 | extract_not_ready | Le MP3 est encore en préparation. extract_failed si la préparation a échoué. |
| 429 | rate_limited | Trop d'appels : attendez le nombre de secondes indiqué par l'en-tête Retry-After. |
| 500 | internal_error | Erreur de notre côté : réessayez, et contactez le support si elle persiste. |
archiveWindow dans GET /streams/{id}).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).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).
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.
| streamIdrequis | uuid | Flux à découper (propre ou suivi en veille), voir GET /streams. |
| fromrequis | date ISO | Début de l'extrait. |
| torequis | date ISO | Fin de l'extrait, 3 h max après le début (24 h avec Réseau). |
| name | texte | Nom de l'extrait et du fichier MP3, 120 caractères max. Défaut : « Extrait ». |
| share | booléen | true pour créer en plus un lien de partage public, valable 30 jours. |
| Idempotency-Key | texte | Facultatif, 200 caractères max. Voir Dates, pagination, idempotence. |
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}'Renvoie l'extrait. Quand status vaut ready, downloadUrl donne le MP3.
{
"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"
}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.
Extraits de l'organisation, du plus récent au plus ancien, qu'ils aient été créés par l'API ou depuis le lecteur.
| limit | entier | 1 à 100, défaut 20. |
| streamId | uuid | Seulement les extraits de ce flux. |
| status | texte | queued, processing, ready ou failed. |
| startingAfter | uuid | Curseur de pagination : nextStartingAfter de la page précédente. |
{
"data": [ { "id": "8b0e7a52-…", "status": "ready", … } ],
"hasMore": true,
"nextStartingAfter": "8b0e7a52-6f1d-4c3a-9d2e-5b7c1a0f9e34"
}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.
Vos flux et les radios suivies en veille (watched: true), avec l'état de la captation et le titre en cours.
{
"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"
}
]
}Ajoute la durée d'archive (retentionDays), la plage découpable (archiveWindow.from → archiveWindow.to) et l'incident en cours éventuel.
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.
| qrequis | texte | Texte recherché. |
| streamId | uuid | Limiter à un flux. |
| periode | texte | 24h, 7j, 30j ou tout (défaut). |
| limit | entier | 1 à 300, défaut 50. |
{
"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"
}
]
}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).
Flux et veille utilisés et disponibles, durée d'archive, options incluses dans vos plans.
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é.
#!/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
donePython, avec requests :
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) :
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 :
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")"
donen8n, 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.
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.