Enqre

Par l’équipe Enqre·Publié le 16/08/2026

QR codes dynamiques depuis Python, Node et C#

Chacun de ces langages a une bonne bibliothèque locale : qrcode pour Python, node-qrcode pour Node, QRCoder pour .NET. Elles dessinent PNG et SVG hors ligne, sans clé, sans quota et sans coût — et pour un code dont la destination ne change jamais, c'est toute la réponse.

L'API sert à l'autre moitié : un code statique est sa destination — l'URL est dans le motif, la déplacer impose de tout réimprimer. Si ce que vous générez sera imprimé, collé sur une machine ou rattaché à un enregistrement qui survivra à la structure d'URL de cette année, le code doit porter une adresse courte que vous contrôlez. C'est de l'hébergement, pas du dessin.

Créer un code

Python

import os, requests

r = requests.post(
    "https://enqre.com/api/v1/qrcodes",
    headers={"Authorization": f"Bearer {os.environ['ENQRE_API_KEY']}"},
    json={
        "name": "Asset 4471 – service log",
        "url": "https://maint.example/assets/4471",
    },
    timeout=10,
)
r.raise_for_status()          # 4xx and 5xx become exceptions, not silence

code = r.json()["data"]
code["id"]        # store this against your record
code["shortUrl"]  # the address the QR image should encode

Node

const res = await fetch("https://enqre.com/api/v1/qrcodes", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.ENQRE_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "Asset 4471 – service log",
    url: "https://maint.example/assets/4471",
  }),
});

// fetch does NOT throw on 4xx. Check the status or you will store undefined.
if (!res.ok) throw new Error(`enqre: ${res.status} ${await res.text()}`);

const { data: code } = await res.json();

Notez la vérification : fetch ne rejette pas sur un 402 ni un 429 ; sans elle vous stockez undefined.

C#

using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("ENQRE_API_KEY"));

var payload = JsonContent.Create(new {
    name = "Asset 4471 – service log",
    url  = "https://maint.example/assets/4471",
});

var res = await http.PostAsync("https://enqre.com/api/v1/qrcodes", payload);
res.EnsureSuccessStatusCode();

using var doc = JsonDocument.Parse(await res.Content.ReadAsStringAsync());
var code = doc.RootElement.GetProperty("data");
var id       = code.GetProperty("id").GetString();
var shortUrl = code.GetProperty("shortUrl").GetString();

Déplacer la destination

PATCH https://enqre.com/api/v1/qrcodes/{id}
Authorization: Bearer enq_…
Content-Type: application/json

{ "url": "https://maint.example/assets/4471/v2" }

Le code imprimé n'est pas touché ; le scan suivant part ailleurs.

Lire les scans

GET /api/v1/qrcodes/{id}/scans répond { total, data }, du plus récent, jusqu'à 1 000 entrées : heure, type d'appareil, système, navigateur.

Ni identité ni localisation — ni ville ni pays.

Ce qui va réellement échouer

  • 401 invalid_api_key
  • 400 invalid_body — presque toujours une URL qui n'en est pas une.
  • 402 plan_limit_reached
  • 429 rate_limited — au-delà de 60 requêtes par minute.

Chaque langage cache l'échec différemment : requests se tait sans raise_for_status, fetch ne rejette que sur erreur réseau, HttpClient réclame EnsureSuccessStatusCode.

Deux règles plus importantes que le code

Rendez la création idempotente. Deux appels créent deux codes.

N'imprimez rien sans relecture.

Quand ne pas écrire d'intégration

Pour quelques centaines de codes en une fois, l'import CSV est plus rapide que tout ce que vous écririez.

Réponses rapides

  • Meilleure bibliothèque ? qrcode, node-qrcode, QRCoder.
  • L'API renvoie-t-elle une image ? Non, shortUrl.
  • Authentification ? Authorization: Bearer enq_….
  • Limite ? 60 par minute.
  • Localisation dans les scans ? Non.
  • Modifiable après impression ? C'est tout l'objet — PATCH.

À lire ensuite