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/codesaceita apenas os tiposurl,vcard,wifi,email,smselocation. Os campos são planos:url; pelo menosvcard_first_nameouvcard_last_name;wifi_ssid;email_to;sms_phone; ou amboslocation_latelocation_lng.- Apenas os códigos
urlpodem ser dinâmicos. As requisições de criação podem incluir opcionalmenteexpires_atcomo carimbo de data/hora ISO 8601;ab_enabled,ab_target_url_beab_weight_a(destinos A/B) são aceitos para códigosurldinâmicos;redirect_after_expirynão faz parte do contrato de criação. GET /v1/codessuporta apenaslimit,cursorestatus(live,paused,flagged,draft).POST /v1/codes/batchaceitaurl,vcardewifi. 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árioskip_url_scan: true.
Criar QR Code
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,q1Resposta (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
| Tipo | Descrição | Campos obrigatórios |
|---|---|---|
url | URL do site (dinâmico ou estático) | url |
vcard | Cartão de visitas (vCard 3.0) | vcard_first_name ou vcard_last_name |
wifi | Configuração de Wi-Fi | wifi_ssid |
email | E-mail (mailto:) | email_to |
sms | SMS | sms_phone |
location | Localização (geo:) | location_lat, location_lng |
Criação em Lote
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 }'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
curl https://qr3.app/v1/codes?status=live&limit=20 \ -H "Authorization: Bearer qr3_sk_..."Parâmetros de Query:
| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
cursor | string | — | Cursor para paginação |
limit | integer | 20 | Resultados por página (máx. 100) |
status | string | — | Filtro: live, paused, flagged, draft |
Obter QR Code
GET /v1/codes/:id
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.
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" }'Landing Page & Links Externos
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;
labeldeve ter entre 1 e 100 caracteres;urldeve serhttp(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.
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.
| Formato | URL | Uso |
|---|---|---|
| SVG (Vetor) | /v1/codes/:code/qr.svg | Web, Escalonamento, Digital |
| PNG (Raster) | /v1/codes/:code/qr.png | E-mail, Apresentações |
| PDF (Vetor) | /v1/codes/:code/qr.pdf | Padrão: quadrado (apenas o código); ?format=a4 para uma folha de impressão |
| EPS (Vetor) | /v1/codes/:code/qr.eps | Fluxos 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)
# 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.pdfCores 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âmetro | Valores | Padrão | SVG, PNG | PDF, EPS |
|---|---|---|---|---|
fg | Hex RRGGBB ou RGB | 000000 | é desenhado | é desenhado como cor de impressão |
bg | Hex como fg ou transparent | ffffff | é desenhado | é desenhado como cor de impressão |
ecc | L, M, Q, H | M | tem efeito | tem 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=lilaretorna a cor salva no código ou, se nenhuma estiver salva, o preto normal, com200e nunca um erro. Apenas um?fg=000000explícito força o preto. bg=transparentretorna 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
1F4E79como 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 debg, 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.
#1F4E79em branco tem 8,7:1,#ff6600em branco apenas 2,9:1. eccaltera 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.QouHtornam o código mais robusto, por exemplo, em papelão ondulado. Um logotipo sempre forçaH.- 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=ffffffdesenha 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.
# 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' });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.
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 noneResposta (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_colorcomo#RRGGBB,background_colorcomo#RRGGBBoutransparent. Outras chaves resultam em400. - Mesclagem: Um campo omitido mantém o seu valor salvo.
nullredefine um campo,"appearance": nullambos. O preto e o branco não são salvos; a resposta os mostra comonull. - Cada resposta de código contém
appearance, bem como os webhooksqr.createdeqr.updated. - Ordem nas rotas de imagem: primeiro o parâmetro, depois a cor salva, depois o padrão.
?fg=000000fornece, 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
fgebg: uma URL sem parâmetros para ambas as cores,?fg=000000para o fundo,?ecc=Qtambé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=2ou oupdated_atdo 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 rejeitamappearancecom422. - 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ível | Quando | Resposta |
|---|---|---|
blocked | Contraste abaixo de 1,5:1 | 422, nada é salvo |
critical | abaixo de 2:1 ou diferença de luminosidade abaixo de 0,30; um aviso juntamente com um logotipo; qualquer fundo transparente | 200 com meta.issues |
warning | abaixo de 4:1 ou diferença de luminosidade abaixo de 0,50; módulos claros sobre fundo escuro | 200 com meta.issues |
| ok | tudo o resto | 200, 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.
Logo
POST /v1/codes/:id/logo
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.
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.
DELETE /v1/codes/:id/logo
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.
# 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 }'