Loy API · piloto com parceiros Documentação para quem desenvolve a integração.

Referência

Base https://loynow.com/api/v1 · versão 1.0.0. Gerada do mesmo contrato OpenAPI que os testes do Loy conferem contra a API — baixe o arquivo para importar no Postman, no Insomnia ou no seu assistente de código.

Conta e catálogo

GET /me #

Retorna identidade, limites e uso diagnóstico da chave

Permissão: qualquer chave válida

Requisição
curl https://loynow.com/api/v1/me \
  -H "Authorization: Bearer $LOY_API_KEY"
Resposta 200 Identidade da empresa autenticada e limites configurados.
Cabeçalhos: Loy-Quota-Limit Loy-Quota-Used Loy-Quota-Reset
{
  "company": {
    "id": 123,
    "name": "Sua empresa"
  },
  "api_key": {
    "prefix": "AbCdEfGh1234",
    "name": "Integração PDV",
    "environment": "live",
    "scopes": [
      "customers:read",
      "customers:write",
      "visits:write"
    ]
  },
  "limits": {
    "plan": "pilot",
    "requests_per_minute": 60,
    "included_requests": 10000
  },
  "usage": {
    "period_start": "2026-10-01",
    "billable_requests": 1280
  }
}

Erros possíveis: 400 · 401 · 403 · 429 · 500 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

GET /services #

Lista os serviços ativos da empresa

Permissão: qualquer chave válida

ParâmetroOndeObrigatórioDescrição
limit integer URL não Itens por página, de 1 a 100 (padrão 25).
starting_after string URL não Valor de next_cursor da página anterior.
Requisição
curl https://loynow.com/api/v1/services \
  -H "Authorization: Bearer $LOY_API_KEY"
Resposta 200 Página de serviços ativos.
{
  "data": [
    {
      "id": "svc_8Lm3Tq1Z",
      "name": "Atendimento completo",
      "price": "49.90",
      "currency": "BRL",
      "points": 1
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Erros possíveis: 401 · 403 · 429 · 500 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

GET /loyalty_programs #

Lista os programas de fidelidade ativos

Permissão: qualquer chave válida

ParâmetroOndeObrigatórioDescrição
limit integer URL não Itens por página, de 1 a 100 (padrão 25).
starting_after string URL não Valor de next_cursor da página anterior.
Requisição
curl https://loynow.com/api/v1/loyalty_programs \
  -H "Authorization: Bearer $LOY_API_KEY"
Resposta 200 Página de programas ativos.
{
  "data": [
    {
      "id": "lp_5Tz1Kw9M",
      "name": "Cartão fidelidade",
      "service_id": "svc_8Lm3Tq1Z",
      "required_visits": 10,
      "reward_description": "Um atendimento grátis"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Erros possíveis: 401 · 403 · 429 · 500 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

Clientes

GET /customers #

Lista clientes da empresa autenticada

Permissão: customers:read

ParâmetroOndeObrigatórioDescrição
limit integer URL não Itens por página, de 1 a 100 (padrão 25).
starting_after string URL não Valor de next_cursor da página anterior.
external_id string URL não Encontra o cliente pelo ID do seu sistema.
email string URL não Encontra o cliente pelo e-mail.
phone string URL não Encontra o cliente pelo telefone (só números).
Requisição
curl https://loynow.com/api/v1/customers \
  -H "Authorization: Bearer $LOY_API_KEY"
Resposta 200 Página de clientes, ordenada por cursor crescente.
{
  "data": [
    {
      "id": "cus_4fRk9P2xQ",
      "external_id": "ERP-991",
      "name": "Ana Souza",
      "email": "ana@exemplo.com",
      "phone": "48999990000",
      "birth_date": "1990-05-14",
      "created_at": "2026-10-08T10:00:00-03:00"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Erros possíveis: 400 · 401 · 403 · 429 · 500 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

POST /customers #

Cadastra cliente sem enviar comunicações automáticas

Permissão: customers:write

ParâmetroOndeObrigatórioDescrição
Idempotency-Key string cabeçalho sim Valor único por operação; repetir a mesma chave não duplica nada.
Requisição
curl -X POST https://loynow.com/api/v1/customers \
  -H "Authorization: Bearer $LOY_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "customer": {
    "name": "Ana Souza",
    "email": "ana@exemplo.com",
    "phone": "48999990000",
    "birth_date": "1990-05-14",
    "external_id": "ERP-991"
  }
}'
Resposta 201 Cliente criado. A resposta é salva para repetições com a mesma chave e corpo.
Cabeçalhos: Idempotent-Replayed
{
  "id": "cus_4fRk9P2xQ",
  "external_id": "ERP-991",
  "name": "Ana Souza",
  "email": "ana@exemplo.com",
  "phone": "48999990000",
  "birth_date": "1990-05-14",
  "created_at": "2026-10-08T10:00:00-03:00"
}

Erros possíveis: 400 · 401 · 403 · 409 · 422 · 429 · 500 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

GET /customers/{id} #

Retorna cliente e resumo de fidelidade

Permissão: customers:read

ParâmetroOndeObrigatórioDescrição
id string caminho sim
Requisição
curl https://loynow.com/api/v1/customers/cus_4fRk9P2xQ \
  -H "Authorization: Bearer $LOY_API_KEY"
Resposta 200 Perfil e resumo calculado pelas regras existentes do Loy.
{
  "customer": {
    "id": "cus_4fRk9P2xQ",
    "external_id": "ERP-991",
    "name": "Ana Souza",
    "email": "ana@exemplo.com",
    "phone": "48999990000",
    "birth_date": "1990-05-14",
    "created_at": "2026-10-08T10:00:00-03:00"
  },
  "summary": {
    "customer_since": "2026-10-08T10:00:00-03:00",
    "appointments_count": 3,
    "rewards_count": 0,
    "available_rewards_count": 0,
    "loyalty_progress": [
      {
        "program_id": "lp_5Tz1Kw9M",
        "name": "Cartão fidelidade",
        "points": 3,
        "required": 10,
        "remaining": 7
      }
    ],
    "missing_info": [
      "birth_date"
    ]
  }
}

Erros possíveis: 401 · 403 · 404 · 429 · 500 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

PATCH /customers/{id} #

Atualiza dados básicos de um cliente

Permissão: customers:write

ParâmetroOndeObrigatórioDescrição
id string caminho sim
Requisição
curl -X PATCH https://loynow.com/api/v1/customers/cus_4fRk9P2xQ \
  -H "Authorization: Bearer $LOY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "customer": {
    "name": "Ana Souza",
    "email": "ana@exemplo.com",
    "phone": "48999990000",
    "birth_date": "1990-05-14",
    "external_id": "ERP-991"
  }
}'
Resposta 200 Cliente atualizado.
{
  "id": "cus_4fRk9P2xQ",
  "external_id": "ERP-991",
  "name": "Ana Souza",
  "email": "ana@exemplo.com",
  "phone": "48999990000",
  "birth_date": "1990-05-14",
  "created_at": "2026-10-08T10:00:00-03:00"
}

Erros possíveis: 401 · 403 · 404 · 409 · 422 · 429 · 500 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

GET /customers/{id}/balance #

Consulta progresso nos programas ativos e recompensas disponíveis

Permissão: customers:read

ParâmetroOndeObrigatórioDescrição
id string caminho sim
Requisição
curl https://loynow.com/api/v1/customers/cus_4fRk9P2xQ/balance \
  -H "Authorization: Bearer $LOY_API_KEY"
Resposta 200 Progresso calculado por LoyaltyProgram#progress_for.
{
  "customer_id": "cus_4fRk9P2xQ",
  "programs": [
    {
      "program_id": "lp_5Tz1Kw9M",
      "name": "Cartão fidelidade",
      "points": 3,
      "required": 10,
      "remaining": 7
    }
  ],
  "available_rewards": [
    {
      "code": "LOY-8KD2QZ",
      "description": "Um atendimento grátis",
      "expires_at": "2026-10-08T10:00:00-03:00"
    }
  ],
  "available_rewards_has_more": false
}

Erros possíveis: 401 · 403 · 404 · 429 · 500 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

Visitas

GET /customers/{id}/visits #

Lista as visitas do cliente, da mais antiga para a mais nova

Permissão: customers:read

ParâmetroOndeObrigatórioDescrição
id string caminho sim
limit integer URL não Itens por página, de 1 a 100 (padrão 25).
starting_after string URL não Valor de next_cursor da página anterior.
Requisição
curl https://loynow.com/api/v1/customers/cus_4fRk9P2xQ/visits \
  -H "Authorization: Bearer $LOY_API_KEY"
Resposta 200 Página de visitas.
{
  "data": [
    {
      "id": "vis_7Hc2Wn5R",
      "customer_id": "cus_4fRk9P2xQ",
      "service_id": "svc_8Lm3Tq1Z",
      "price": "49.90",
      "currency": "BRL",
      "points": 1,
      "paid": true,
      "notes": "Pedido #8812",
      "created_at": "2026-10-08T10:00:00-03:00"
    }
  ],
  "has_more": true,
  "next_cursor": "string"
}

Erros possíveis: 400 · 401 · 403 · 404 · 429 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

POST /visits #

Registra uma visita paga e aplica as regras do programa de fidelidade

Único caminho para pontos entrarem pela API. Mesmas regras do app: pontos, recompensa conquistada e avisos. Se a empresa escolheu que o próprio sistema avisa o cliente, o Loy não envia nada ao cliente final.

Permissão: visits:write

ParâmetroOndeObrigatórioDescrição
Idempotency-Key string cabeçalho sim Valor único por operação; repetir a mesma chave não duplica nada.
Requisição
curl -X POST https://loynow.com/api/v1/visits \
  -H "Authorization: Bearer $LOY_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "visit": {
    "customer_id": "cus_4fRk9P2xQ",
    "service_id": "svc_8Lm3Tq1Z",
    "price": "49.90",
    "points": 1,
    "notes": "Pedido #8812"
  }
}'
Resposta 201 Visita registrada, com recompensas conquistadas e progresso atualizado.
Cabeçalhos: Idempotent-Replayed
{
  "id": "vis_7Hc2Wn5R",
  "customer_id": "cus_4fRk9P2xQ",
  "service_id": "svc_8Lm3Tq1Z",
  "price": "49.90",
  "currency": "BRL",
  "points": 1,
  "paid": true,
  "notes": "Pedido #8812",
  "created_at": "2026-10-08T10:00:00-03:00",
  "loyalty": {
    "rewards_earned": [
      {
        "id": "rwd_2Pq8Xs4K",
        "code": "LOY-8KD2QZ",
        "description": "Um atendimento grátis",
        "expires_at": "2026-10-08T10:00:00-03:00"
      }
    ],
    "programs": [
      {
        "program_id": "lp_5Tz1Kw9M",
        "points": 3,
        "required": 10,
        "remaining": 7
      }
    ]
  }
}

Erros possíveis: 400 · 401 · 403 · 404 · 409 · 422 · 429 · 500 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

GET /visits/{id} #

Consulta uma visita

Permissão: customers:read

ParâmetroOndeObrigatórioDescrição
id string caminho sim
Requisição
curl https://loynow.com/api/v1/visits/vis_7Hc2Wn5R \
  -H "Authorization: Bearer $LOY_API_KEY"
Resposta 200 Visita.
{
  "id": "vis_7Hc2Wn5R",
  "customer_id": "cus_4fRk9P2xQ",
  "service_id": "svc_8Lm3Tq1Z",
  "price": "49.90",
  "currency": "BRL",
  "points": 1,
  "paid": true,
  "notes": "Pedido #8812",
  "created_at": "2026-10-08T10:00:00-03:00"
}

Erros possíveis: 401 · 403 · 404 · 429 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

Recompensas

GET /customers/{id}/rewards #

Lista as recompensas do cliente

Permissão: rewards:read

ParâmetroOndeObrigatórioDescrição
id string caminho sim
status string URL não
limit integer URL não Itens por página, de 1 a 100 (padrão 25).
starting_after string URL não Valor de next_cursor da página anterior.
Requisição
curl https://loynow.com/api/v1/customers/cus_4fRk9P2xQ/rewards \
  -H "Authorization: Bearer $LOY_API_KEY"
Resposta 200 Página de recompensas.
{
  "data": [
    {
      "id": "rwd_2Pq8Xs4K",
      "customer_id": "cus_4fRk9P2xQ",
      "code": "LOY-8KD2QZ",
      "title": "Recompensa de fidelidade",
      "description": "Um atendimento grátis",
      "status": "available",
      "origin": "loyalty_program",
      "program_id": "lp_5Tz1Kw9M",
      "earned_at": "2026-10-08T10:00:00-03:00",
      "expires_at": "2026-10-08T10:00:00-03:00",
      "used_at": "2026-10-08T10:00:00-03:00"
    }
  ],
  "has_more": true,
  "next_cursor": "string"
}

Erros possíveis: 400 · 401 · 403 · 404 · 429 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

GET /rewards/lookup #

Busca a recompensa pelo código que o cliente mostra no caixa

Permissão: rewards:read

ParâmetroOndeObrigatórioDescrição
code string URL sim Código que o cliente mostra no celular.
Requisição
curl "https://loynow.com/api/v1/rewards/lookup?code=LOY-8KD2QZ" \
  -H "Authorization: Bearer $LOY_API_KEY"
Resposta 200 Recompensa encontrada (confira `status` antes de resgatar).
{
  "id": "rwd_2Pq8Xs4K",
  "customer_id": "cus_4fRk9P2xQ",
  "code": "LOY-8KD2QZ",
  "title": "Recompensa de fidelidade",
  "description": "Um atendimento grátis",
  "status": "available",
  "origin": "loyalty_program",
  "program_id": "lp_5Tz1Kw9M",
  "earned_at": "2026-10-08T10:00:00-03:00",
  "expires_at": "2026-10-08T10:00:00-03:00",
  "used_at": "2026-10-08T10:00:00-03:00"
}

Erros possíveis: 401 · 403 · 404 · 429 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

GET /rewards/{id} #

Consulta uma recompensa

Permissão: rewards:read

ParâmetroOndeObrigatórioDescrição
id string caminho sim
Requisição
curl https://loynow.com/api/v1/rewards/rwd_2Pq8Xs4K \
  -H "Authorization: Bearer $LOY_API_KEY"
Resposta 200 Recompensa.
{
  "id": "rwd_2Pq8Xs4K",
  "customer_id": "cus_4fRk9P2xQ",
  "code": "LOY-8KD2QZ",
  "title": "Recompensa de fidelidade",
  "description": "Um atendimento grátis",
  "status": "available",
  "origin": "loyalty_program",
  "program_id": "lp_5Tz1Kw9M",
  "earned_at": "2026-10-08T10:00:00-03:00",
  "expires_at": "2026-10-08T10:00:00-03:00",
  "used_at": "2026-10-08T10:00:00-03:00"
}

Erros possíveis: 401 · 403 · 404 · 429 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

POST /rewards/{id}/redeem #

Resgata a recompensa (marca como utilizada)

Mesma regra do app. Um segundo resgate da mesma recompensa recebe 409 reward_already_redeemed; recompensa vencida recebe 422 reward_expired. Repetir com a mesma Idempotency-Key devolve a resposta original.

Permissão: rewards:redeem

ParâmetroOndeObrigatórioDescrição
id string caminho sim
Idempotency-Key string cabeçalho sim Valor único por operação; repetir a mesma chave não duplica nada.
Requisição
curl -X POST https://loynow.com/api/v1/rewards/rwd_2Pq8Xs4K/redeem \
  -H "Authorization: Bearer $LOY_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
Resposta 200 Recompensa resgatada.
Cabeçalhos: Idempotent-Replayed
{
  "id": "rwd_2Pq8Xs4K",
  "customer_id": "cus_4fRk9P2xQ",
  "code": "LOY-8KD2QZ",
  "title": "Recompensa de fidelidade",
  "description": "Um atendimento grátis",
  "status": "available",
  "origin": "loyalty_program",
  "program_id": "lp_5Tz1Kw9M",
  "earned_at": "2026-10-08T10:00:00-03:00",
  "expires_at": "2026-10-08T10:00:00-03:00",
  "used_at": "2026-10-08T10:00:00-03:00"
}

Erros possíveis: 400 · 401 · 403 · 404 · 409 · 422 · 429 · 500 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

Avisos (webhooks)

GET /webhook_endpoints #

Lista os endereços de webhook ativos ou pausados

Permissão: webhooks:manage

ParâmetroOndeObrigatórioDescrição
limit integer URL não Itens por página, de 1 a 100 (padrão 25).
starting_after string URL não Valor de next_cursor da página anterior.
Requisição
curl https://loynow.com/api/v1/webhook_endpoints \
  -H "Authorization: Bearer $LOY_API_KEY"
Resposta 200 Página de endereços (sem o segredo).
{
  "data": [
    {
      "id": "we_3Hd8Lp2V",
      "url": "https://hooks.seusistema.com/loy",
      "event_types": [
        "visit.recorded",
        "reward.earned"
      ],
      "status": "enabled",
      "failure_streak": 0,
      "last_success_at": "2026-10-08T10:00:00-03:00",
      "created_at": "2026-10-08T10:00:00-03:00"
    }
  ],
  "has_more": true,
  "next_cursor": "string"
}

Erros possíveis: 401 · 403 · 429 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

POST /webhook_endpoints #

Cadastra um endereço HTTPS público para receber eventos

O segredo de assinatura (whsec_…) aparece só nesta resposta.

Permissão: webhooks:manage

Requisição
curl -X POST https://loynow.com/api/v1/webhook_endpoints \
  -H "Authorization: Bearer $LOY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "webhook_endpoint": {
    "url": "https://hooks.seusistema.com/loy",
    "event_types": [
      "customer.created"
    ]
  }
}'
Resposta 201 Endereço criado, com o segredo (mostrado uma única vez).
{
  "id": "we_3Hd8Lp2V",
  "url": "https://hooks.seusistema.com/loy",
  "event_types": [
    "visit.recorded",
    "reward.earned"
  ],
  "status": "enabled",
  "failure_streak": 0,
  "last_success_at": "2026-10-08T10:00:00-03:00",
  "created_at": "2026-10-08T10:00:00-03:00",
  "secret": "whsec_9xQ2…"
}

Erros possíveis: 401 · 403 · 409 · 422 · 429 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

DELETE /webhook_endpoints/{id} #

Remove o endereço (entregas pendentes são canceladas)

Permissão: webhooks:manage

ParâmetroOndeObrigatórioDescrição
id string caminho sim
Requisição
curl -X DELETE https://loynow.com/api/v1/webhook_endpoints/we_3Hd8Lp2V \
  -H "Authorization: Bearer $LOY_API_KEY"
Resposta 204 Removido.

Erros possíveis: 401 · 403 · 404 · 429 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

POST /webhook_endpoints/{id}/enable #

Reativa um endereço pausado por falhas

Permissão: webhooks:manage

ParâmetroOndeObrigatórioDescrição
id string caminho sim
Requisição
curl -X POST https://loynow.com/api/v1/webhook_endpoints/we_3Hd8Lp2V/enable \
  -H "Authorization: Bearer $LOY_API_KEY"
Resposta 200 Endereço reativado.
{
  "id": "we_3Hd8Lp2V",
  "url": "https://hooks.seusistema.com/loy",
  "event_types": [
    "visit.recorded",
    "reward.earned"
  ],
  "status": "enabled",
  "failure_streak": 0,
  "last_success_at": "2026-10-08T10:00:00-03:00",
  "created_at": "2026-10-08T10:00:00-03:00"
}

Erros possíveis: 401 · 403 · 404 · 422 · 429 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

POST /webhook_endpoints/{id}/test #

Envia agora um evento ping assinado e conta o resultado

Permissão: webhooks:manage

ParâmetroOndeObrigatórioDescrição
id string caminho sim
Requisição
curl -X POST https://loynow.com/api/v1/webhook_endpoints/we_3Hd8Lp2V/test \
  -H "Authorization: Bearer $LOY_API_KEY"
Resposta 200 Resultado do envio.
{
  "delivered": true,
  "response_status": 200,
  "error": "string"
}

Erros possíveis: 401 · 403 · 404 · 429 · 503 — sempre no mesmo formato, com code e request_id. O que fazer em cada um.

O acesso é liberado pela equipe do Loy. Pedir acesso.