Pular para o conteúdo

API de QR Codes

Visão Geral

A API de Codes é o coração do qr3.app. Com ela, você cria, atualiza e exclui QR codes dinâmicos e estáticos.

URL Base: https://qr3.app/v1/codes

Contrato REST vinculativo

O contrato seguinte aplica-se a todos os clientes:

  • POST /v1/codes aceita apenas os tipos url, vcard, wifi, email, sms e location. Os campos são planos: url; pelo menos vcard_first_name ou vcard_last_name; wifi_ssid; email_to; sms_phone; ou ambos location_lat e location_lng.
  • Apenas os códigos url podem ser dinâmicos. As requisições de criação podem incluir opcionalmente expires_at como carimbo de data/hora ISO 8601; ab_enabled, ab_target_url_b e ab_weight_a (destinos A/B) são aceitos para códigos url dinâmicos; redirect_after_expiry não faz parte do contrato de criação.
  • GET /v1/codes suporta apenas limit, cursor e status (live, paused, flagged, draft).
  • POST /v1/codes/batch aceita url, vcard e wifi. O limite é 10 para Free, 500 para Pro e 1.000 registros para Business/Agency/Enterprise por requisição. As análises de URL são executadas de forma síncrona para, no máximo, 50 itens URL; acima de 50 é necessário skip_url_scan: true.

Criar QR Code

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

Resposta (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" }
}

Tipos de QR Code

TipoDescriçãoCampos obrigatórios
urlURL do site (dinâmico ou estático)url
vcardCartão de visitas (vCard 3.0)vcard_first_name ou vcard_last_name
wifiConfiguração de Wi-Fiwifi_ssid
emailE-mail (mailto:)email_to
smsSMSsms_phone
locationLocalização (geo:)location_lat, location_lng

Criação em Lote

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

Resposta (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
}
}

Lista de QR Codes

GET /v1/codes

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

Parâmetros de Query:

ParâmetroTipoPadrãoDescrição
cursorstring—Cursor para paginação
limitinteger20Resultados por página (máx. 100)
statusstring—Filtro: live, paused, flagged, draft

Obter QR Code

GET /v1/codes/:id

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

Atualizar QR Code

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.

Os QR codes dinâmicos permitem alterar a URL de destino a qualquer momento — sem a necessidade de reimprimir o QR code.

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

Para códigos url dinâmicos, você pode definir is_landing_page: true (na criação ou via PATCH). O escaneamento exibirá uma página hospedada pelo qr3 com os arquivos públicos e links externos do código, em vez de redirecionar. Os links externos são passados como uma array links :

{
"is_landing_page": true,
"links": [
{ "label": "Datenblatt", "url": "https://example.com/datenblatt.pdf" },
{ "label": "Zertifikat", "url": "https://example.com/zertifikat.pdf" }
]
}
  • 0 a 20 links por código; label deve ter entre 1 e 100 caracteres; url deve ser http(s) (≤ 2048 caracteres).
  • Cada URL é verificada com o Google Web Risk — uma URL insegura retorna 422.
  • Se o Web Risk não estiver acessível no momento do salvamento, o link será aceito mesmo assim, mas marcado para nova verificação. Uma tarefa diária verifica novamente os links salvos (e reavalia periodicamente os links classificados como seguros) e pausa o código automaticamente se um link for posteriormente identificado como inseguro.
  • "links": [] exclui todos os links. Consulte o Guia de Landing Page.

Excluir QR Code

DELETE /v1/codes/:id

Exclusão lógica (Soft-Delete) — o QR code é arquivado, os dados de escaneamento são mantidos.

Um segundo DELETE do mesmo código retorna 404, mesmo se ambas as requisições chegarem ao mesmo tempo. O webhook qr.deleted é enviado exatamente uma vez.

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

Baixar Imagens do QR

Todos os formatos de imagem são acessíveis publicamente — nenhuma autenticação é necessária.

FormatoURLUso
SVG (Vetor)/v1/codes/:code/qr.svgWeb, Escalonamento, Digital
PNG (Raster)/v1/codes/:code/qr.pngE-mail, Apresentações
PDF (Vetor)/v1/codes/:code/qr.pdfPadrão: quadrado (apenas o código); ?format=a4 para uma folha de impressão
EPS (Vetor)/v1/codes/:code/qr.epsFluxos de trabalho de impressão profissional (Adobe, gráficas)

Opcional: ?size=N — Tamanho do módulo em pixels (2–20, padrão: 4) para SVG, PNG e EPS. O PDF utiliza um tamanho de módulo fixo.

Apenas PDF: ?format=a4|square — Formato da página (padrão: square — apenas código + zona de silêncio, sem espaço em branco A4; a4 para uma folha A4 pronta para impressão)

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

Cores e correção de erros

Todas as quatro rotas de imagem aceitam três parâmetros opcionais. Eles aplicam-se a essa requisição específica e têm prioridade sobre as cores salvas no código (próxima seção).

ParâmetroValoresPadrãoSVG, PNGPDF, EPS
fgHex RRGGBB ou RGB000000é desenhadoé desenhado como cor de impressão
bgHex como fg ou transparentffffffé desenhadoé desenhado como cor de impressão
eccL, M, Q, HMtem efeitotem efeito
  • Grafia: Diferenciação entre maiúsculas e minúsculas não importa, o # é opcional. Quem o enviar deve codificá-lo como %23.
  • Valores inválidos contam como não definidos. ?fg=lila retorna a cor salva no código ou, se nenhuma estiver salva, o preto normal, com 200 e nunca um erro. Apenas um ?fg=000000 explícito força o preto.
  • bg=transparent retorna um SVG, PDF ou EPS sem fundo e um PNG com canal alfa real. A superfície sobre a qual o código é colocado deve ser clara e deixar uma zona de silêncio livre de 4 módulos ao redor. Um código escuro sobre um fundo escuro não é legível.
  • PDF e EPS escrevem preto e cinza como escala de cinza (apenas placa preta) e qualquer outra cor como CMYK em porcentagens inteiras, por exemplo 1F4E79 como C74 M36 Y0 K53. Assim que uma cor é escolhida, uma área opaca fica por trás do código e da sua zona de silêncio, branca ou na cor de bg, tal como no SVG. Sem cores, ambos os arquivos permanecem inalterados. Conversão e limites: Cores na impressão.
  • Contraste: A rota de imagem não o verifica. Recomenda-se pelo menos 4:1 e módulos escuros sobre fundo claro. #1F4E79 em branco tem 8,7:1, #ff6600 em branco apenas 2,9:1.
  • ecc altera o padrão de pontos, não o conteúdo. Um código impresso continua a funcionar, mas não misture arquivos de impressão antigos e novos. Q ou H tornam o código mais robusto, por exemplo, em papelão ondulado. Um logotipo sempre força H.
  • Com logotipo a área atrás do logotipo permanece branca, mesmo com fundo colorido ou transparente.
  • Armazenamento em cache: Apenas a imagem padrão real (preto no branco, correção de erros M, sem logotipo) é fornecida como imutável por 24 horas; qualquer outra renderização por 5 minutos. Para PDF e EPS, qualquer fundo fornecido conta como um desvio: bg=ffffff desenha um preenchimento branco que o arquivo padrão não possui.
  • Plano: Cores e correção de erros estão disponíveis em todos os planos, inclusive no gratuito.
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

Salvar cores no código

PATCH /v1/codes/:id salva as cores como appearance no código. As rotas de imagem passam a desenhá-las por padrão, sem parâmetros.

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

Resposta (HTTP 200, abreviada):

{
"data": {
"id": "qr_a1b2c3d4",
"short_code": "r7f3Kx",
"appearance": { "foreground_color": "#1F4E79", "background_color": null }
},
"meta": { "request_id": "req_xyz", "issues": [] }
}
  • Valores: foreground_color como #RRGGBB, background_color como #RRGGBB ou transparent. Outras chaves resultam em 400.
  • Mesclagem: Um campo omitido mantém o seu valor salvo. null redefine um campo, "appearance": null ambos. O preto e o branco não são salvos; a resposta os mostra como null.
  • Cada resposta de código contém appearance, bem como os webhooks qr.created e qr.updated.
  • Ordem nas rotas de imagem: primeiro o parâmetro, depois a cor salva, depois o padrão. ?fg=000000 fornece, portanto, o arquivo de impressão preto de um código colorido.
  • Imagens incorporadas: Uma URL de imagem segue as cores salvas, desde que não as defina ela própria com fg e bg: uma URL sem parâmetros para ambas as cores, ?fg=000000 para o fundo, ?ecc=Q também para ambas. Após uma alteração de cor, uma página que incorpore tal URL ainda pode exibir a imagem antiga: por até 24 horas se a URL fornecia a imagem padrão até então (preto no branco, correção de erros M, sem logotipo), caso contrário, por até 5 minutos. A solução é um parâmetro próprio na URL que mude a cada alteração de cor, como ?v=2 ou o updated_at do código como no dashboard. As rotas de imagem ignoram parâmetros desconhecidos.
  • Correção de erros nunca é salva. É selecionada por download com ?ecc=.
  • Apenas via PATCH: POST /v1/codes, o lote e a importação rejeitam appearance com 422.
  • PDF e EPS desenham as cores salvas como cores de impressão, tal como os parâmetros. Como o branco nunca é salvo, um código com uma cor de primeiro plano salva recebe ali um preenchimento branco, tal como no SVG.

Verificação de contraste

A API verifica o par resultante da requisição e do valor salvo:

NívelQuandoResposta
blockedContraste abaixo de 1,5:1422, nada é salvo
criticalabaixo de 2:1 ou diferença de luminosidade abaixo de 0,30; um aviso juntamente com um logotipo; qualquer fundo transparente200 com meta.issues
warningabaixo de 4:1 ou diferença de luminosidade abaixo de 0,50; módulos claros sobre fundo escuro200 com meta.issues
oktudo o resto200, meta.issues está vazio

Cada entrada em meta.issues tem code, severity, field, message e, opcionalmente, hints como contrast_ratio — o mesmo formato que as mensagens de conformidade de um Passaporte Digital do Produto. Um fundo transparente nunca é bloqueado, porque um código claro sobre uma embalagem escura é um caso de uso real. O fundo ainda assim necessita de um contraste claro e de uma zona de silêncio livre de 4 módulos ao seu redor.

O envio e a remoção de um logotipo (POST e DELETE /v1/codes/:id/logo) verificam as cores salvas da mesma forma e também fornecem os resultados em meta.issues: com um logotipo, um aviso torna-se critical, sem um logotipo volta a ser um aviso.

Se outra requisição alterar o mesmo código no mesmo instante, a API aplica as alterações ao estado mais recente. Apenas se isto falhar três vezes consecutivas é que responderá com 409; o cliente então recarrega o código e repete a alteração.


Requisição multipart, campo file: PNG, JPEG ou WebP, no máximo 1 MB, detectado pelos magic bytes. Normaliza a imagem para um 512×512-PNG transparente e substitui um logo existente.

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

Resposta (HTTP 201): o código atualizado, com o logo_file_id definido.

Remove o logo e elimina o objeto armazenado. Idempotente — uma chamada sem um logo existente continua a retornar 200.

Se outra requisição alterar o logo do mesmo código no mesmo instante (um segundo upload ou uma remoção), POST e DELETE /v1/codes/:id/logo respondem com 409 (errors/conflict) e não alteram nada; uma imagem enviada é descartada. Recarregue o código e tente novamente. Duas chamadas simultâneas de DELETE /v1/codes/:id/logo não constituem um conflito; ambas retornam 200.

Se estiver definido, todos os quatro formatos — qr.svg, qr.png, qr.pdf e qr.eps — incorporam os pixels do logo e aumentam a correção de erros para H. O contrato completo — incluindo qual alteração (adicionar/remover vs. substituir) altera o padrão de pontos — bem como as instruções de impressão, estão disponíveis em Logo no código QR.


Comentários

Os comentários permitem ciclos de feedback entre agências e clientes.

GET /v1/codes/:id/comments

POST /v1/codes/:id/comments

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

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

Os comentários do Dashboard são atribuídos ao usuário criador (author_id); comentários criados por meio de API-Keys puras permanecem não atribuídos (author_id: null). Apenas o próprio autor ou um org_admin/ws_admin pode excluir um comentário — API-Keys puras só podem excluir comentários não atribuídos criados via API.

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