QR-Codes API
Overzicht
De Codes-API is het hart van qr3.app. Hiermee kun je dynamische en statische QR-codes maken, bijwerken en verwijderen.
Basis-URL: https://qr3.app/v1/codes
Bindend REST-contract
Het volgende contract geldt voor alle clients:
POST /v1/codesaccepteert uitsluitend de typenurl,vcard,wifi,email,smsenlocation. Velden zijn plat:url; ten minstevcard_first_nameofvcard_last_name;wifi_ssid;email_to;sms_phone; of beidelocation_latenlocation_lng.- Alleen
url-codes kunnen dynamisch zijn. Aanmaakverzoeken kunnen optioneelexpires_atals ISO 8601-tijdstempel bevatten;ab_enabled,ab_target_url_benab_weight_a(A/B-bestemmingen) zijn toegestaan voor dynamischeurl-codes;redirect_after_expirymaakt geen deel uit van het aanmaakcontract. GET /v1/codesondersteunt alleenlimit,cursorenstatus(live,paused,flagged,draft).POST /v1/codes/batchaccepteerturl,vcardenwifi. De limiet is 10 voor Free, 500 voor Pro en 1.000 records voor Business/Agency/Enterprise per verzoek. URL-scans worden synchroon uitgevoerd voor maximaal 50 URL-items; boven 50 isskip_url_scan: truevereist.
QR-code maken
POST /v1/codes
curl -X POST https://qr3.app/v1/codes \ -H "Authorization: Bearer qr3_sk_..." \ -H "Content-Type: application/json" \ -d '{ "type": "url", "url": "https://example.com", "title": "Mein erster QR-Code", "tags": ["marketing", "q1"], "is_dynamic": true }'const code = await qr3.codes.create({ type: 'url', url: 'https://example.com', title: 'Mein erster QR-Code', tags: ['marketing', 'q1'], is_dynamic: true,});qr3 create https://example.com --title "Mein QR-Code" --tags marketing,q1Response (HTTP 201):
{ "data": { "id": "qr_a1b2c3d4", "short_code": "r7f3Kx", "redirect_url": "https://qr3.app/r7f3Kx", "image_svg_url": "https://qr3.app/v1/codes/r7f3Kx/qr.svg", "image_png_url": "https://qr3.app/v1/codes/r7f3Kx/qr.png", "image_pdf_url": "https://qr3.app/v1/codes/r7f3Kx/qr.pdf", "image_eps_url": "https://qr3.app/v1/codes/r7f3Kx/qr.eps", "type": "url", "target_url": "https://example.com", "is_dynamic": true, "status": "live", "tags": ["marketing", "q1"], "total_scans": 0, "created_at": "2026-03-15T10:00:00.000Z" }, "meta": { "request_id": "req_xyz123" }}QR-code-typen
| Type | Beschrijving | Verplichte velden |
|---|---|---|
url | Website-URL (dynamisch of statisch) | url |
vcard | Visitekaartje (vCard 3.0) | vcard_first_name of vcard_last_name |
wifi | Wifi-configuratie | wifi_ssid |
email | E-mail (mailto:) | email_to |
sms | Sms | sms_phone |
location | Locatie (geo:) | location_lat, location_lng |
Batch-creatie
POST /v1/codes/batch
curl -X POST https://qr3.app/v1/codes/batch \ -H "Authorization: Bearer qr3_sk_..." \ -H "Content-Type: application/json" \ -d '{ "items": [ { "type": "url", "url": "https://produkt-1.example.com", "tags": ["batch"] }, { "type": "url", "url": "https://produkt-2.example.com", "tags": ["batch"] }, { "type": "wifi", "wifi_ssid": "GastWLAN", "wifi_password": "geheim123" } ], "skip_url_scan": false }'Response (HTTP 201):
{ "data": { "created": [ { "id": "qr_...", "short_code": "abc123", "redirect_url": "https://qr3.app/abc123" }, { "id": "qr_...", "short_code": "def456", "redirect_url": "https://qr3.app/def456" }, { "id": "qr_...", "short_code": "ghi789", "status": "live" } ], "total": 3, "failed": 0 }}QR-codelijst
GET /v1/codes
curl https://qr3.app/v1/codes?status=live&limit=20 \ -H "Authorization: Bearer qr3_sk_..."Query-parameters:
| Parameter | Type | Standaard | Beschrijving |
|---|---|---|---|
cursor | string | — | Cursor voor paginering |
limit | integer | 20 | Resultaten per pagina (max. 100) |
status | string | — | Filter: live, paused, flagged, draft |
QR-code ophalen
GET /v1/codes/:id
curl https://qr3.app/v1/codes/qr_a1b2c3d4 \ -H "Authorization: Bearer qr3_sk_..."QR-code bijwerken
PATCH /v1/codes/:id
Update contract: url may be changed only for an existing type: "url" code, and its value must use http:// or https://. Other code types must not receive url; invalid requests return 422.
Dynamische QR-codes maken het mogelijk om de bestemmings-URL op elk moment te wijzigen — zonder dat de QR-code opnieuw gedrukt hoeft te worden.
curl -X PATCH https://qr3.app/v1/codes/qr_a1b2c3d4 \ -H "Authorization: Bearer qr3_sk_..." \ -H "Content-Type: application/json" \ -d '{ "url": "https://neue-zielseite.example.com", "status": "live" }'Bestemmingspagina & externe links
Voor dynamische url-codes kun je is_landing_page: true instellen (bij het maken of via PATCH). Een scan toont dan een door qr3 gehoste pagina met de openbare bestanden en externe links van de code, in plaats van door te sturen. Externe links worden doorgegeven als een links-array:
{ "is_landing_page": true, "links": [ { "label": "Datenblatt", "url": "https://example.com/datenblatt.pdf" }, { "label": "Zertifikat", "url": "https://example.com/zertifikat.pdf" } ]}- 0–20 links per code;
labelis 1–100 tekens;urlmoethttp(s)zijn (≤ 2048 tekens). - Elke URL wordt gecontroleerd met Google Web Risk — een onveilige URL retourneert
422. - Als Web Risk bij het opslaan niet bereikbaar is, wordt de link toch geaccepteerd, maar gemarkeerd voor een nieuwe controle. Een dagelijkse taak controleert opgeslagen links opnieuw (en controleert als veilig geclassificeerde links regelmatig opnieuw) en pauzeert de code automatisch als een link later als onveilig wordt herkend.
"links": []verwijdert alle links. Zie de handleiding voor bestemmingspagina’s.
QR-code verwijderen
DELETE /v1/codes/:id
Soft-delete — de QR-code wordt gearchiveerd, scangegevens blijven behouden.
Een tweede DELETE op dezelfde code retourneert 404, zelfs als beide aanvragen tegelijkertijd aankomen. De qr.deleted webhook wordt precies één keer verzonden.
curl -X DELETE https://qr3.app/v1/codes/qr_a1b2c3d4 \ -H "Authorization: Bearer qr3_sk_..."QR-afbeeldingen downloaden
Alle afbeeldingsformaten zijn openbaar toegankelijk — geen authenticatie vereist.
| Formaat | URL | Gebruik |
|---|---|---|
| SVG (vector) | /v1/codes/:code/qr.svg | Web, schalen, digitaal |
| PNG (raster) | /v1/codes/:code/qr.png | E-mail, presentaties |
| PDF (vector) | /v1/codes/:code/qr.pdf | Standaard: vierkant (alleen de code); ?format=a4 voor een printvel |
| EPS (vector) | /v1/codes/:code/qr.eps | Professionele drukwerk-workflows (Adobe, drukkerijen) |
Optioneel: ?size=N — modulegrootte in pixels (2–20, standaard: 4) voor SVG, PNG en EPS. De PDF gebruikt een vaste modulegrootte.
Alleen PDF: ?format=a4|square — paginaformaat (standaard: square — alleen code + quiet zone, geen A4-witruimte; a4 voor een printklaar A4-vel)
# SVG für Webcurl https://qr3.app/v1/codes/r7f3Kx/qr.svg
# PNG in hoher Auflösungcurl https://qr3.app/v1/codes/r7f3Kx/qr.png?size=10 -o qr-hires.png
# Kompaktes PDF (nur der Code, Standard)curl https://qr3.app/v1/codes/r7f3Kx/qr.pdf -o qr.pdf
# Druckfertiges A4-Blattcurl "https://qr3.app/v1/codes/r7f3Kx/qr.pdf?format=a4" -o qr-a4.pdfKleuren en foutcorrectie
Alle vier de afbeeldingsroutes accepteren drie optionele parameters. Ze gelden voor deze specifieke opvraging en hebben voorrang op kleuren die bij de code zijn opgeslagen (volgende sectie).
| Parameter | Waarden | Standaard | SVG, PNG | PDF, EPS |
|---|---|---|---|---|
fg | Hex RRGGBB of RGB | 000000 | wordt getekend | wordt getekend als drukkleur |
bg | Hex zoals fg of transparent | ffffff | wordt getekend | wordt getekend als drukkleur |
ecc | L, M, Q, H | M | heeft effect | heeft effect |
- Schrijfwijze: Hoofdlettergevoeligheid maakt niet uit, de
#is optioneel. Bij het verzenden wordt deze gecodeerd als%23. - Ongeldige waarden tellen als niet ingesteld.
?fg=lilalevert de op de code opgeslagen kleur, of het normale zwart als er geen is opgeslagen, met200en nooit een fout. Alleen een expliciete?fg=000000dwingt zwart af. bg=transparentlevert een SVG, PDF of EPS zonder achtergrond en een PNG met een echt alfakanaal. De ondergrond waarop de code wordt geplaatst, moet licht zijn en rondom 4 modules stille zone vrijlaten. Een donkere code op een donkere ondergrond is niet leesbaar.- PDF en EPS schrijven zwart en grijs als grijswaarden (alleen zwartplaat) en elke andere kleur als CMYK in hele procenten, bijvoorbeeld
1F4E79als C74 M36 Y0 K53. Zodra er een kleur is gekozen, ligt er achter de code en de stille zone een dekkend vlak, wit of in de kleur vanbg, net als bij de SVG. Zonder kleuren blijven beide bestanden ongewijzigd. Omrekening en beperkingen: Drukkleuren. - Leesbaarheid: De afbeeldingsroute controleert het contrast niet. Aanbevolen is minimaal 4:1 en donkere modules op een lichte achtergrond.
#1F4E79op wit heeft 8,7:1,#ff6600op wit slechts 2,9:1. eccwijzigt het puntenpatroon, niet de inhoud. Een gedrukte code blijft werken, maar oude en nieuwe drukbestanden mogen niet worden gemengd.QofHmaken de code robuuster, bijvoorbeeld op golfkarton. Een logo vereist altijdH.- Met logo blijft het vlak achter het logo wit, ook bij een gekleurde of transparante achtergrond.
- Caching: Alleen de feitelijke standaardafbeelding (zwart op wit, foutcorrectie M, geen logo) wordt gedurende 24 uur als onveranderlijk geleverd; elke andere weergave gedurende 5 minuten. Voor PDF en EPS geldt elke opgegeven achtergrond als een afwijking:
bg=fffffftekent daar een wit vlak dat het standaardbestand niet heeft. - Tarief: Kleuren en foutcorrectie zijn beschikbaar in elk tarief, ook in het gratis tarief.
# Dark blue code on whitecurl "https://qr3.app/v1/codes/r7f3Kx/qr.svg?fg=1F4E79" -o qr-blue.svg
# Transparent PNG for a layout on a light surfacecurl "https://qr3.app/v1/codes/r7f3Kx/qr.png?size=10&bg=transparent" -o qr-transparent.png
# More robust for corrugated board: error correction Qcurl "https://qr3.app/v1/codes/r7f3Kx/qr.pdf?ecc=Q" -o qr-q.pdf// @qr3/sdk 1.2.0 or later — imageUrl() only builds the URL, it sends no request// Dark blue code on whiteqr3.codes.imageUrl('r7f3Kx', { format: 'svg', fg: '1F4E79' });// → https://qr3.app/v1/codes/r7f3Kx/qr.svg?fg=1F4E79
// Transparent PNG for a layout on a light surfaceqr3.codes.imageUrl('r7f3Kx', { format: 'png', size: 10, bg: 'transparent' });
// More robust for corrugated board: error correction Qqr3.codes.imageUrl('r7f3Kx', { format: 'pdf', ecc: 'Q' });Kleuren bij de code opslaan
PATCH /v1/codes/:id slaat kleuren op als appearance bij de code. De afbeeldingsroutes tekenen deze dan standaard, zonder parameters.
curl -X PATCH https://qr3.app/v1/codes/qr_a1b2c3d4 \ -H "Authorization: Bearer qr3_sk_..." \ -H "Content-Type: application/json" \ -d '{"appearance": {"foreground_color": "#1F4E79"}}'// @qr3/sdk 1.2.0 or laterconst code = await qr3.codes.update('qr_a1b2c3d4', { appearance: { foreground_color: '#1F4E79' },});code.appearance; // { foreground_color: '#1F4E79', background_color: null }code.issues; // contrast check findings, absent when there are noneAntwoord (HTTP 200, ingekort):
{ "data": { "id": "qr_a1b2c3d4", "short_code": "r7f3Kx", "appearance": { "foreground_color": "#1F4E79", "background_color": null } }, "meta": { "request_id": "req_xyz", "issues": [] }}- Waarden:
foreground_colorals#RRGGBB,background_colorals#RRGGBBoftransparent. Andere sleutels resulteren in400. - Samenvoegen: Een weggelaten veld behoudt zijn opgeslagen waarde.
nullreset een veld,"appearance": nullbeide. Zwart en wit worden niet opgeslagen; het antwoord toont ze alsnull. - Elk code-antwoord bevat
appearance, evenals de webhooksqr.createdenqr.updated. - Volgorde in de afbeeldingsroutes: eerst de parameter, dan de opgeslagen kleur, dan de standaard.
?fg=000000levert daarom het zwarte drukbestand van een gekleurde code op. - Ingebedde afbeeldingen: Een afbeeldings-URL volgt de opgeslagen kleuren voor zover deze die niet zelf met
fgenbgvastlegt: een URL zonder parameters voor beide kleuren,?fg=000000voor de achtergrond,?ecc=Qeveneens voor beide. Na een kleurwijziging kan een pagina die een dergelijke URL insluit nog de oude afbeelding tonen: tot 24 uur als de URL tot dan toe de standaardafbeelding leverde (zwart op wit, foutcorrectie M, zonder logo), anders tot 5 minuten. De oplossing is een eigen parameter aan de URL die bij elke kleurwijziging verandert, zoals?v=2of deupdated_atvan de code zoals in het dashboard. De afbeeldingsroutes negeren onbekende parameters. - Foutcorrectie wordt nooit opgeslagen. Deze wordt per download gekozen met
?ecc=. - Alleen via
PATCH:POST /v1/codes, de batch en de import weigerenappearancemet422. - PDF en EPS tekenen opgeslagen kleuren als drukkleuren, net als de parameters. Omdat wit nooit wordt opgeslagen, krijgt een code met een opgeslagen voorgrondkleur daar een wit vlak, net als in de SVG.
Contrastcontrole
De API controleert het paar dat voortvloeit uit de aanvraag en de opgeslagen waarde:
| Niveau | Wanneer | Antwoord |
|---|---|---|
blocked | contrast onder 1,5:1 | 422, er wordt niets opgeslagen |
critical | onder 2:1 of helderheidsverschil onder 0,30; een waarschuwing samen met een logo; elke transparante achtergrond | 200 met meta.issues |
warning | onder 4:1 of helderheidsverschil onder 0,50; lichte modules op een donkere achtergrond | 200 met meta.issues |
| ok | al het andere | 200, meta.issues is leeg |
Elk item in meta.issues heeft code, severity, field, message en optioneel hints zoals contrast_ratio — dezelfde vorm als de compliance-meldingen van een digitaal productpaspoort. Een transparante achtergrond wordt nooit geblokkeerd, omdat een lichte code op een donkere verpakking een echte use-case is. De ondergrond heeft desondanks een duidelijk contrast nodig en rondom een vrije rustzone van 4 modules.
Het uploaden en verwijderen van een logo (POST en DELETE /v1/codes/:id/logo) voeren dezelfde controle uit op de opgeslagen kleuren en retourneren de bevindingen eveneens in meta.issues: met een logo wordt een waarschuwing critical, zonder logo is het weer een waarschuwing.
Als een andere aanvraag dezelfde code op hetzelfde moment wijzigt, past de API de wijzigingen toe op de nieuwste status. Pas als dit drie keer achter elkaar mislukt, antwoordt deze met 409; de client laadt de code dan opnieuw en herhaalt de wijziging.
Logo
POST /v1/codes/:id/logo
Multipart-request, veld file: PNG, JPEG of WebP, maximaal 1 MB, herkend aan de Magic Bytes. Normaliseert de afbeelding naar een transparante 512×512-PNG en vervangt een bestaand logo.
curl -X POST https://qr3.app/v1/codes/qr_a1b2c3d4/logo \ -H "Authorization: Bearer qr3_sk_..." \Antwoord (HTTP 201): de bijgewerkte code, met ingestelde logo_file_id.
DELETE /v1/codes/:id/logo
Verwijdert het logo en wist het opgeslagen object. Idempotent — een aanroep zonder bestaand logo retourneert nog steeds 200.
Als een andere aanvraag tegelijkertijd het logo van dezelfde code wijzigt (een tweede upload of een verwijdering), antwoorden POST en DELETE /v1/codes/:id/logo met 409 (errors/conflict) en wijzigen ze niets; een geüpload logo wordt weggegooid. Laad de code opnieuw en probeer het nogmaals. Twee gelijktijdige aanroepen van DELETE /v1/codes/:id/logo zijn geen conflict; beide retourneren 200.
Indien ingesteld, sluiten alle vier de formaten — qr.svg, qr.png, qr.pdf en qr.eps — de logo-pixels in en verhogen ze de foutcorrectie naar H. Het volledige contract — inclusief welke wijziging (toevoegen/verwijderen vs. vervangen) het stippenpatroon verandert — evenals printinstructies zijn te vinden onder Logo in de QR-code.
Reacties
Reacties maken feedbackcycli tussen bureaus en klanten mogelijk.
GET /v1/codes/:id/comments
POST /v1/codes/:id/comments
PATCH /v1/codes/:id/comments/:commentId
DELETE /v1/codes/:id/comments/:commentId
Dashboard-reacties worden toegewezen aan de gebruiker die ze heeft aangemaakt (author_id); reacties via pure API-keys blijven niet-toegewezen (author_id: null). Alleen de auteur zelf of een org_admin/ws_admin mag een reactie verwijderen — pure API-keys kunnen alleen niet-toegewezen API-reacties verwijderen.
# Kommentar hinzufügencurl -X POST https://qr3.app/v1/codes/qr_a1b2c3d4/comments \ -H "Authorization: Bearer qr3_sk_..." \ -H "Content-Type: application/json" \ -d '{ "body": "QR-Code bitte auf grünen Hintergrund abstimmen.", "author_name": "Max Müller" }'
# Offene Kommentare auflistencurl "https://qr3.app/v1/codes/qr_a1b2c3d4/comments?resolved=false" \ -H "Authorization: Bearer qr3_sk_..."
# Kommentar als erledigt markierencurl -X PATCH https://qr3.app/v1/codes/qr_a1b2c3d4/comments/cmt_xyz \ -H "Authorization: Bearer qr3_sk_..." \ -H "Content-Type: application/json" \ -d '{ "resolved": true }'