Voltar ao início

Documentação da API

API RESTful para integrar o FluxQR nas suas aplicações.

Versão 1.0 · Base URL: /api/v1

Introdução

A API do FluxQR permite criar e gerir QR codes dinâmicos, consultar analytics e gerir a sua conta de forma programática. Todas as respostas são em formato JSON.

Base URL

https://fluxqr.com/api/v1

Headers obrigatórios

Content-Type: application/json
Accept: application/json
Authorization: Bearer <your-api-token>

Pode gerar tokens de API em Definições → API Tokens.

Autenticação

A API usa tokens Bearer via Laravel Sanctum. Pode obter um token via login ou criando um na interface web.

POST
/api/v1/auth/register

Criar nova conta

PUBLIC
POST
/api/v1/auth/login

Obter token de autenticação

PUBLIC
POST
/api/v1/auth/logout

Revogar o token atual

GET
/api/v1/auth/user

Obter utilizador autenticado

Registar

Cria uma nova conta e retorna um token de acesso.

ParâmetroTipoObrigatórioDescrição
namestringSimNome do utilizador
emailstringSimEmail (único)
passwordstringSimPassword (mín. 8 caracteres)
password_confirmationstringSimConfirmação da password
device_namestringNãoNome do dispositivo (default: "api")
curl -X POST /api/v1/auth/register \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "João Silva",
    "email": "joao@example.com",
    "password": "password123",
    "password_confirmation": "password123"
  }'

Resposta (201):

{
  "user": {
    "id": 1,
    "name": "João Silva",
    "email": "joao@example.com",
    "locale": null,
    "timezone": null,
    "email_verified_at": null,
    "two_factor_enabled": false,
    "created_at": "2026-03-16T12:00:00+00:00"
  },
  "token": "1|abc123def456..."
}

Login

ParâmetroTipoObrigatórioDescrição
emailstringSimEmail do utilizador
passwordstringSimPassword
device_namestringNãoNome do dispositivo
curl -X POST /api/v1/auth/login \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "email": "joao@example.com",
    "password": "password123"
  }'

Resposta (200):

{
  "user": { "id": 1, "name": "João Silva", ... },
  "token": "2|xyz789..."
}

Logout

Revoga o token usado no pedido.

curl -X POST /api/v1/auth/logout \
  -H "Authorization: Bearer <token>" \
  -H "Accept: application/json"

QR Codes

CRUD completo para gerir QR codes dinâmicos. Todos os endpoints requerem autenticação.

GET
/api/v1/qr-codes

Listar todos os QR codes

POST
/api/v1/qr-codes

Criar novo QR code

GET
/api/v1/qr-codes/{id}

Ver detalhe de um QR code

PUT
/api/v1/qr-codes/{id}

Atualizar QR code

DELETE
/api/v1/qr-codes/{id}

Eliminar QR code

PATCH
/api/v1/qr-codes/{id}/toggle-status

Alternar status (ativo/pausado)

Listar QR Codes

ParâmetroTipoObrigatórioDescrição
searchstringNãoPesquisar por nome, URL ou short code
statusstringNãoFiltrar por status: active, paused, archived
per_pageintegerNãoItens por página (default: 15)
pageintegerNãoNúmero da página
curl -X GET "/api/v1/qr-codes?status=active&per_page=10" \
  -H "Authorization: Bearer <token>" \
  -H "Accept: application/json"

Resposta (200):

{
  "data": [
    {
      "id": 1,
      "name": "Campanha Verão",
      "short_code": "aBcDeFg",
      "destination_url": "https://example.com/summer",
      "redirect_url": "https://fluxqr.com/r/aBcDeFg",
      "redirect_mode": 302,
      "status": "active",
      "expires_at": null,
      "scans_count": 142,
      "created_at": "2026-03-10T10:00:00+00:00",
      "updated_at": "2026-03-15T14:30:00+00:00"
    }
  ],
  "links": { "first": "...", "last": "...", "prev": null, "next": "..." },
  "meta": { "current_page": 1, "last_page": 3, "per_page": 10, "total": 25 }
}

Criar QR Code

ParâmetroTipoObrigatórioDescrição
namestringSimNome do QR code (máx. 255)
destination_urlstringSimURL de destino (máx. 2048)
curl -X POST /api/v1/qr-codes \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "Menu Restaurante",
    "destination_url": "https://meurestaurante.pt/menu"
  }'

Resposta (201):

{
  "data": {
    "id": 5,
    "name": "Menu Restaurante",
    "short_code": "xYz1234",
    "destination_url": "https://meurestaurante.pt/menu",
    "redirect_url": "https://fluxqr.com/r/xYz1234",
    "redirect_mode": 302,
    "status": "active",
    "expires_at": null,
    "created_at": "2026-03-16T15:00:00+00:00",
    "updated_at": "2026-03-16T15:00:00+00:00"
  }
}

Atualizar QR Code

ParâmetroTipoObrigatórioDescrição
namestringSimNovo nome
destination_urlstringSimNovo URL de destino (apenas planos pagos)

Nota: No plano Free, a edição do destination_url é ignorada. Faça upgrade para alterar URLs.

curl -X PUT /api/v1/qr-codes/5 \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "Menu Atualizado",
    "destination_url": "https://meurestaurante.pt/menu-novo"
  }'

Eliminar QR Code

curl -X DELETE /api/v1/qr-codes/5 \
  -H "Authorization: Bearer <token>" \
  -H "Accept: application/json"

Resposta (200):

{ "message": "QR code deleted." }

Alternar Status

Alterna entre active e paused.

curl -X PATCH /api/v1/qr-codes/5/toggle-status \
  -H "Authorization: Bearer <token>" \
  -H "Accept: application/json"

Analytics

Consultar métricas, séries temporais e scans detalhados.

GET
/api/v1/analytics/dashboard

Métricas globais do workspace

GET
/api/v1/analytics/qr-codes/{id}

Métricas de um QR code específico

GET
/api/v1/analytics/qr-codes/{id}/scans

Listar scans de um QR code (paginado)

Dashboard

ParâmetroTipoObrigatórioDescrição
daysintegerNãoPeríodo em dias para time series (default: 30)
limitintegerNãoLimite de resultados para top/recent (default: 5)
curl -X GET "/api/v1/analytics/dashboard?days=7" \
  -H "Authorization: Bearer <token>" \
  -H "Accept: application/json"

Resposta (200):

{
  "metrics": {
    "total_scans": 12450,
    "scans_today": 85,
    "scans_today_change": 12.5,
    "scans_7_days": 520,
    "scans_7_days_change": -3.2,
    "scans_30_days": 2100,
    "scans_30_days_change": 15.0,
    "total_qr_codes": 45,
    "active_qr_codes": 38
  },
  "time_series": [
    { "date": "2026-03-10", "count": 72 },
    { "date": "2026-03-11", "count": 95 }
  ],
  "top_qr_codes": [
    { "id": 1, "name": "Campanha Verão", "short_code": "aBcDeFg", "scan_count": 142 }
  ],
  "recent_qr_codes": [
    { "id": 5, "name": "Menu", "short_code": "xYz1234", "destination_url": "...", "status": "active", "scans_count": 10 }
  ]
}

Analytics de QR Code

curl -X GET /api/v1/analytics/qr-codes/1 \
  -H "Authorization: Bearer <token>" \
  -H "Accept: application/json"

Resposta (200):

{
  "qr_code": { "id": 1, "name": "Campanha Verão", "short_code": "aBcDeFg" },
  "metrics": {
    "total_scans": 142,
    "scans_today": 5,
    "scans_7_days": 38,
    "scans_30_days": 120
  },
  "time_series": [ { "date": "2026-03-16", "count": 5 } ],
  "recent_scans": [
    {
      "id": 501,
      "scanned_at": "2026-03-16T14:32:00+00:00",
      "device_type": "mobile",
      "referrer": "instagram.com",
      "country": "PT",
      "is_bot": false
    }
  ]
}

Listar Scans

ParâmetroTipoObrigatórioDescrição
per_pageintegerNãoItens por página (default: 25)
pageintegerNãoNúmero da página
curl -X GET "/api/v1/analytics/qr-codes/1/scans?per_page=10" \
  -H "Authorization: Bearer <token>" \
  -H "Accept: application/json"

Resposta (200):

{
  "data": [
    {
      "id": 501,
      "qr_code_id": 1,
      "scanned_at": "2026-03-16T14:32:00+00:00",
      "device_type": "mobile",
      "os": "iOS",
      "browser": "Safari",
      "country": "PT",
      "region": "Lisboa",
      "city": "Lisboa",
      "language": "pt-PT",
      "referrer": "instagram.com",
      "is_bot": false
    }
  ],
  "links": { ... },
  "meta": { "current_page": 1, "total": 142, ... }
}

Billing

Consultar planos, limites de utilização e gerir subscrição.

GET
/api/v1/plans

Listar planos disponíveis

PUBLIC
GET
/api/v1/billing

Plano atual e limites de utilização

POST
/api/v1/billing/upgrade

Fazer upgrade para Pro

POST
/api/v1/billing/downgrade

Fazer downgrade para Free

Listar Planos

curl -X GET /api/v1/plans \
  -H "Accept: application/json"

Resposta (200):

{
  "plans": [
    {
      "id": 1,
      "name": "Free",
      "slug": "free",
      "is_free": true,
      "limits": {
        "max_qrcodes": 3,
        "max_scans_monthly": 1000,
        "max_custom_domains": 0,
        "max_api_keys": 1,
        "max_members": 1,
        "features": []
      }
    },
    {
      "id": 2,
      "name": "Pro",
      "slug": "pro",
      "is_free": false,
      "limits": { "max_qrcodes": 50, "max_scans_monthly": 100000, ... }
    }
  ]
}

Plano Atual & Utilização

curl -X GET /api/v1/billing \
  -H "Authorization: Bearer <token>" \
  -H "Accept: application/json"

Resposta (200):

{
  "limits": {
    "plan_name": "Free",
    "plan_slug": "free",
    "max_qrcodes": 3,
    "max_scans_monthly": 1000,
    "used_qrcodes": 2,
    "used_scans": 150,
    "remaining_qrcodes": 1,
    "remaining_scans": 850
  }
}

Upgrade / Downgrade

# Upgrade para Pro
curl -X POST /api/v1/billing/upgrade \
  -H "Authorization: Bearer <token>" \
  -H "Accept: application/json"

# Downgrade para Free
curl -X POST /api/v1/billing/downgrade \
  -H "Authorization: Bearer <token>" \
  -H "Accept: application/json"

Perfil

Gerir dados do utilizador autenticado.

GET
/api/v1/profile

Ver perfil

PATCH
/api/v1/profile

Atualizar perfil

PUT
/api/v1/profile/password

Alterar password

DELETE
/api/v1/profile

Eliminar conta

Atualizar Perfil

ParâmetroTipoObrigatórioDescrição
namestringNãoNome (máx. 255)
emailstringNãoEmail (único)
localestringNãoIdioma: pt ou en
timezonestringNãoTimezone (ex: Europe/Lisbon)
curl -X PATCH /api/v1/profile \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "name": "João Silva", "locale": "pt" }'

Alterar Password

ParâmetroTipoObrigatórioDescrição
current_passwordstringSimPassword atual
passwordstringSimNova password (mín. 8 caracteres)
password_confirmationstringSimConfirmação da nova password
curl -X PUT /api/v1/profile/password \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "current_password": "oldpassword",
    "password": "newpassword123",
    "password_confirmation": "newpassword123"
  }'

Eliminar Conta

Atenção: Esta ação é irreversível. Todos os dados, QR codes e tokens serão eliminados.

ParâmetroTipoObrigatórioDescrição
passwordstringSimPassword atual para confirmação
curl -X DELETE /api/v1/profile \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "password": "yourpassword" }'

Erros

A API utiliza códigos de estado HTTP convencionais. Respostas de erro incluem sempre um campo message.

CódigoSignificadoDescrição
200OKPedido bem-sucedido
201CreatedRecurso criado com sucesso
401UnauthorizedToken inválido ou ausente
403ForbiddenSem permissão para este recurso
404Not FoundRecurso não encontrado
422UnprocessableErro de validação ou limite atingido
429Too Many RequestsRate limit excedido
500Server ErrorErro interno do servidor

Formato de erro de validação (422)

{
  "message": "The name field is required.",
  "errors": {
    "name": ["The name field is required."],
    "destination_url": ["The destination url must be a valid URL."]
  }
}

Rate Limits

A API aplica limites de taxa para garantir a estabilidade do serviço.

ContextoLimite
API geral (autenticado)60 pedidos / minuto
Login / Registo5 pedidos / minuto
Redirect público (/r/)60 pedidos / minuto

Quando o limite é excedido, receberá uma resposta 429 Too Many Requests. Aguarde o tempo indicado no header Retry-After.