Gå til indhold

QR-koder API

Oversigt

Codes-API’en er hjertet i qr3.app. Med den kan du oprette, opdatere og slette dynamiske og statiske QR-koder.

Basis-URL: https://qr3.app/v1/codes

Bindende REST-kontrakt

Følgende kontrakt gælder for alle klienter:

  • POST /v1/codes accepterer kun typerne url, vcard, wifi, email, sms og location. Felterne er flade: url; mindst vcard_first_name eller vcard_last_name; wifi_ssid; email_to; sms_phone; eller location_lat og location_lng.
  • Kun url-koder kan være dynamiske. Oprettelsesanmodninger kan valgfrit indeholde expires_at som et ISO 8601-tidspunkt; ab_enabled, ab_target_url_b og ab_weight_a (A/B-destinationer) accepteres for dynamiske url-koder; redirect_after_expiry er ikke en del af oprettelseskontrakten.
  • GET /v1/codes understøtter kun limit, cursor og status (live, paused, flagged, draft).
  • POST /v1/codes/batch accepterer url, vcard og wifi. Grænsen er 10 for Free, 500 for Pro og 1.000 poster for Business/Agency/Enterprise pr. anmodning. URL-scanninger kører synkront for højst 50 URL-poster; over 50 kræves skip_url_scan: true.

Opret QR-kode

POST /v1/codes

Terminal window
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
}'

Response (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-kodetyper

TypeBeskrivelsePåkrævede felter
urlWebsite-URL (dynamisk eller statisk)url
vcardVisitkort (vCard 3.0)vcard_first_name eller vcard_last_name
wifiWi-Fi-konfigurationwifi_ssid
emailE-mail (mailto:)email_to
smsSMSsms_phone
locationLokation (geo:)location_lat, location_lng

Batch-oprettelse

POST /v1/codes/batch

Terminal window
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-kodeliste

GET /v1/codes

Terminal window
curl https://qr3.app/v1/codes?status=live&limit=20 \
-H "Authorization: Bearer qr3_sk_..."

Query-parametre:

ParameterTypeStandardBeskrivelse
cursorstring—Cursor til paginering
limitinteger20Resultater pr. side (maks. 100)
statusstring—Filter: live, paused, flagged, draft

Hent QR-kode

GET /v1/codes/:id

Terminal window
curl https://qr3.app/v1/codes/qr_a1b2c3d4 \
-H "Authorization: Bearer qr3_sk_..."

Opdater QR-kode

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.

Dynamiske QR-koder gør det muligt at ændre destinations-URL’en når som helst — uden at skulle genprinte QR-koden.

Terminal window
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" }'

For dynamiske url-koder kan du angive is_landing_page: true (ved oprettelse eller via PATCH). En scanning vil derefter vise en side hostet af qr3 med kodens offentlige filer og eksterne links i stedet for at viderestille. Eksterne links overføres som et 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 pr. kode; label er 1–100 tegn; url skal være http(s) (≤ 2048 tegn).
  • Hver URL kontrolleres med Google Web Risk — en usikker URL returnerer 422.
  • Hvis Web Risk ikke er tilgængelig under lagring, accepteres linket stadig, men markeres til fornyet kontrol. Et dagligt job kontrollerer gemte links igen (og tjekker regelmæssigt links, der tidligere blev klassificeret som sikre) og sætter automatisk koden på pause, hvis et link senere identificeres som usikkert.
  • "links": [] sletter alle links. Se vejledningen til landingssider.

Slet QR-kode

DELETE /v1/codes/:id

Soft-delete — QR-koden arkiveres, scanningsdata bevares.

Et andet DELETE på den samme kode returnerer 404, selvom begge anmodninger ankommer på samme tid. Webhooken qr.deleted sendes nøjagtig én gang.

Terminal window
curl -X DELETE https://qr3.app/v1/codes/qr_a1b2c3d4 \
-H "Authorization: Bearer qr3_sk_..."

Download QR-billeder

Alle billedformater er offentligt tilgængelige — ingen godkendelse påkrævet.

FormatURLAnvendelse
SVG (vektor)/v1/codes/:code/qr.svgWeb, skalering, digital
PNG (raster)/v1/codes/:code/qr.pngE-mail, præsentationer
PDF (vektor)/v1/codes/:code/qr.pdfStandard: kvadratisk (kun koden); ?format=a4 til et printark
EPS (vektor)/v1/codes/:code/qr.epsProfessionelle print-workflows (Adobe, trykkerier)

Valgfrit: ?size=N — modulstørrelse i pixels (2–20, standard: 4) for SVG, PNG og EPS. PDF’en bruger en fast modulstørrelse.

Kun PDF: ?format=a4|square — sideformat (standard: square — kun kode + quiet zone, intet hvidt A4-område; a4 til et printklart A4-ark)

Terminal window
# SVG für Web
curl https://qr3.app/v1/codes/r7f3Kx/qr.svg
# PNG in hoher Auflösung
curl 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-Blatt
curl "https://qr3.app/v1/codes/r7f3Kx/qr.pdf?format=a4" -o qr-a4.pdf

Farver og fejlkorrektion

Alle fire billedruter accepterer tre valgfrie parametre. De gælder for denne ene anmodning og har forrang over farver, der er gemt på koden (næste afsnit).

ParameterVærdierStandardSVG, PNGPDF, EPS
fgHex RRGGBB eller RGB000000tegnestegnes som en trykfarve
bgHex som fg eller transparentfffffftegnestegnes som en trykfarve
eccL, M, Q, HMhar effekthar effekt
  • Skrivemåde: Der skelnes ikke mellem store og små bogstaver, og # er valgfrit. Hvis det sendes med, skal det kodes som %23.
  • Ugyldige værdier tæller som ikke angivet. ?fg=lila returnerer den farve, der er gemt på koden, eller den normale sorte, hvis der ikke er gemt nogen, med 200 og aldrig en fejl. Kun en eksplicit ?fg=000000 gennemtvinger sort.
  • bg=transparent returnerer en SVG, PDF eller EPS uden baggrund og en PNG med en ægte alfakanal. Underlaget, som koden placeres på, skal være lyst og efterlade en frizone på 4 moduler hele vejen rundt. En mørk kode på et mørkt underlag er ikke læsbar.
  • PDF og EPS skriver sort og grå som gråtone (kun sortplade) og enhver anden farve som CMYK i hele procenter, for eksempel 1F4E79 som C74 M36 Y0 K53. Så snart der vælges en farve, ligger der en dækkende flade bag koden og dens frizone, hvid eller i farven fra bg, ligesom i SVG-filen. Uden farver forbliver begge filer uændrede. Konvertering og begrænsninger: Farver i tryk.
  • Læsbarhed: Billedruten kontrollerer ikke kontrasten. Det anbefales at have mindst 4:1 og mørke moduler på en lys baggrund. #1F4E79 på hvid har 8,7:1, #ff6600 på hvid kun 2,9:1.
  • ecc ændrer punktmønstret, ikke indholdet. En trykt kode fungerer fortsat, men gamle og nye trykfiler må ikke blandes. Q eller H gør koden mere robust, for eksempel på bølgepap. Et logo gennemtvinger altid H.
  • Med logo forbliver området bag logoet hvidt, selv ved en farvet eller transparent baggrund.
  • Caching: Kun det faktiske standardbillede (sort på hvidt, fejlkorrektion M, intet logo) leveres som uforanderligt i 24 timer; enhver anden gengivelse i 5 minutter. For PDF og EPS tæller enhver angiven baggrund som en afvigelse: bg=ffffff tegner der en hvid udfyldning, som standardfilen ikke har.
  • Abonnement: Farver og fejlkorrektion er tilgængelige i alle abonnementer, også i det gratis.
Terminal window
# Dark blue code on white
curl "https://qr3.app/v1/codes/r7f3Kx/qr.svg?fg=1F4E79" -o qr-blue.svg
# Transparent PNG for a layout on a light surface
curl "https://qr3.app/v1/codes/r7f3Kx/qr.png?size=10&bg=transparent" -o qr-transparent.png
# More robust for corrugated board: error correction Q
curl "https://qr3.app/v1/codes/r7f3Kx/qr.pdf?ecc=Q" -o qr-q.pdf

Gem farver på koden

PATCH /v1/codes/:id gemmer farver som appearance på koden. Billedruterne tegner dem derefter som standard, uden parametre.

Terminal window
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"}}'

Svar (HTTP 200, forkortet):

{
"data": {
"id": "qr_a1b2c3d4",
"short_code": "r7f3Kx",
"appearance": { "foreground_color": "#1F4E79", "background_color": null }
},
"meta": { "request_id": "req_xyz", "issues": [] }
}
  • Værdier: foreground_color som #RRGGBB, background_color som #RRGGBB eller transparent. Andre nøgler resulterer i 400.
  • Sammenfletning: Et udeladt felt beholder sin gemte værdi. null nulstiller et felt, "appearance": null nulstiller begge. Sort og hvid gemmes ikke; svaret viser dem som null.
  • Ethvert kodesvar indeholder appearance, ligesom webhookene qr.created og qr.updated.
  • Rækkefølge i billedruterne: først parameteren, derefter den gemte farve, derefter standarden. ?fg=000000 leverer derfor den sorte trykfil af en farvet kode.
  • Indlejrede billeder: En billed-URL følger de gemte farver, så længe den ikke selv fastlægger dem med fg og bg: en URL uden parametre for begge farver, ?fg=000000 for baggrunden, ?ecc=Q ligeledes for begge. Efter en farveændring kan en side, der indlejrer en sådan URL, stadig vise det gamle billede: i op til 24 timer, hvis URL’en indtil da leverede standardbilledet (sort på hvidt, fejlkorrektion M, uden logo), ellers i op til 5 minutter. Afhjælpningen er en egen parameter på URL’en, som ændrer sig med hver farveændring, f.eks. ?v=2 eller kodens updated_at som i dashboardet. Billedruterne ignorerer ukendte parametre.
  • Fejlkorrektion gemmes aldrig. Den vælges pr. download med ?ecc=.
  • Kun via PATCH: POST /v1/codes, batch-kørslen og importen afviser appearance med 422.
  • PDF og EPS tegner gemte farver som trykfarver, præcis ligesom parametrene. Da hvid aldrig gemmes, får en kode med en gemt forgrundsfarve en hvid udfyldning der, ligesom i SVG.

Kontrastkontrol

API’en kontrollerer det par, der resulterer af anmodningen og den gemte værdi:

NiveauHvornårSvar
blockedKontrast under 1,5:1422, intet gemmes
criticalunder 2:1 eller lysstyrkeforskel under 0,30; en advarsel sammen med et logo; enhver transparent baggrund200 med meta.issues
warningunder 4:1 eller lysstyrkeforskel under 0,50; lyse moduler på mørk baggrund200 med meta.issues
okalt andet200, meta.issues er tom

Hver post i meta.issues har code, severity, field, message og valgfrit hints som contrast_ratio — samme form som overensstemmelsesmeddelelserne for et digitalt produktpas. En transparent baggrund blokeres aldrig, fordi en lys kode på mørk emballage er et reelt anvendelsestilfælde. Underlaget har dog stadig brug for en tydelig kontrast og en fri frizone på 4 moduler hele vejen rundt.

Upload og fjernelse af et logo (POST og DELETE /v1/codes/:id/logo) kontrollerer ligeledes de gemte farver og returnerer også resultaterne i meta.issues: med et logo bliver en advarsel til critical, uden et logo er det en advarsel igen.

Hvis en anden anmodning ændrer den samme kode i samme øjeblik, anvender API’en ændringerne på den nyeste tilstand. Først når dette mislykkes tre gange i træk, svarer den med 409; klienten indlæser derefter koden igen og gentager ændringen.


Multipart-anmodning, feltet file: PNG, JPEG eller WebP, højst 1 MB, identificeret ud fra magic bytes. Normaliserer billedet til en gennemsigtig 512×512-PNG og erstatter et eksisterende logo.

Terminal window
curl -X POST https://qr3.app/v1/codes/qr_a1b2c3d4/logo \
-H "Authorization: Bearer qr3_sk_..." \

Svar (HTTP 201): den opdaterede kode, med logo_file_id angivet.

Fjerner logoet og sletter det gemte objekt. Idempotent — et kald uden et eksisterende logo returnerer stadig 200.

Hvis en anden anmodning ændrer den samme kodes logo i samme øjeblik (en anden upload eller en fjernelse), svarer POST og DELETE /v1/codes/:id/logo med 409 (errors/conflict) og ændrer intet; et uploadet billede kasseres. Indlæs koden igen, og prøv igen. To samtidige kald af DELETE /v1/codes/:id/logo er ikke en konflikt; begge returnerer 200.

Hvis det er angivet, indlejrer alle fire formater — qr.svg, qr.png, qr.pdf og qr.eps — logo-pixelene og hæver fejlkorrektionen til H. Den fulde kontrakt — herunder hvilken ændring (tilføjelse/fjernelse vs. udskiftning) der ændrer prikmønstret — samt udskrivningsvejledninger findes under Logo i QR-koden.


Kommentarer

Kommentarer muliggør feedback-loops mellem bureauer og kunder.

GET /v1/codes/:id/comments

POST /v1/codes/:id/comments

PATCH /v1/codes/:id/comments/:commentId

DELETE /v1/codes/:id/comments/:commentId

Dashboard-kommentarer tilskrives den bruger, der opretter dem (author_id); kommentarer oprettet via rene API-nøgler forbliver uden tilskrivning (author_id: null). En kommentar må kun slettes af forfatteren selv eller af en org_admin/ws_admin — rene API-nøgler kan kun slette ikke-tilskrevne API-kommentarer.

Terminal window
# Kommentar hinzufügen
curl -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 auflisten
curl "https://qr3.app/v1/codes/qr_a1b2c3d4/comments?resolved=false" \
-H "Authorization: Bearer qr3_sk_..."
# Kommentar als erledigt markieren
curl -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 }'