Desenvolvedores · v1.1.0

Integre com o IngressoJá

Ligue a catraca, o CRM ou o ERP aos seus eventos, ou use o IngressoJá como gateway e receba por PIX no seu próprio sistema. Exemplos reais em cURL, Node.js, Python e PHP.

https://api.ingressoja.com/v1

Começando

Visão geral

São duas APIs no mesmo endereço. Escolha a do seu caso:

API de eventos e ingressos

Para quem vende ingressos no IngressoJá: eventos, setores, pedidos, participantes, check-in na catraca e avisos em tempo real.

Acesso: token Bearer ij_… · valores em centavos

Começar

API de pagamentos (PIX)

Para o parceiro que já tem o próprio sistema e quer receber pelo IngressoJá: gera o PIX, mostra ao cliente e recebe o aviso quando pagar.

Acesso: x-public-key + x-secret-key · valores em reais

Começar

Começando

Início rápido

  1. 1Pegue o acesso no painel. Eventos: Integrações › API, criar token. Pagamentos: menu API, chave pública e privada.
  2. 2Guarde no servidor, em variável de ambiente (INGRESSOJA_TOKEN, INGRESSOJA_SECRET_KEY). Nunca no site ou no app.
  3. 3Faça a primeira chamada e confira a resposta:
Seus eventos
curl "https://api.ingressoja.com/v1/events?status=published" \
  -H "Authorization: Bearer SEU_TOKEN"
Um PIX de R$ 10,00
curl -X POST "https://api.ingressoja.com/v1/gateway/pix/receive" \
  -H "x-public-key: SUA_CHAVE_PUBLICA" \
  -H "x-secret-key: SUA_CHAVE_PRIVADA" \
  -H "Content-Type: application/json" \
  -d '{"identifier":"teste-1","amount":10,"client":{"name":"Ana Ribeiro","email":"ana.ribeiro@gmail.com","document":"52998224725"}}'

Começando

Formato, paginação e erros

  • JSON em UTF-8, sempre por HTTPS.
  • Datas em ISO 8601, UTC (2026-11-07T01:00:00.000Z = 6/11 às 22h em Brasília). O fuso dos eventos é America/Sao_Paulo.
  • API de eventos: valores em centavos (8000 = R$ 80,00) e o conteúdo em data. API de pagamentos: valores em reais (89.9).
  • Listas paginadas por cursor: ?limit= (1 a 200, padrão 50). Enquanto pagination.has_more for true, peça a próxima com ?cursor= + pagination.next_cursor.
  • Limite da API de eventos: 120 pedidos por minuto por token. Passou, volta 429: espere alguns segundos.
Erro da API de eventos
{
  "error": {
    "code": "event_not_found",
    "message": "Evento não encontrado."
  }
}
Erro da API de pagamentos
{
  "statusCode": 400,
  "errorCode": "VALIDATION_ERROR",
  "message": "Documento do cliente inválido",
  "details": {
    "field": "customer.document",
    "issue": "Documento do cliente inválido"
  }
}
StatuscodeQuando (API de eventos)
400invalid_status / invalid_date / invalid_sessionParâmetro com valor inválido.
401missing_token / invalid_tokenToken ausente, errado ou revogado.
403insufficient_scopeO token não tem a permissão da rota (leitura ou check-in).
404event_not_found / order_not_found / ticket_not_foundNão existe, ou não é da sua conta.
429rate_limitedMais de 120 pedidos por minuto com o mesmo token.

API de eventos e ingressos

Autenticação

No painel, abra Integrações › API e crie um token. Escolha as permissões: leitura (eventos, pedidos e ingressos) e/ou check-in (validar ingresso na entrada). O token aparece uma única vez: se perder, revogue e crie outro.

Envie em toda chamada no cabeçalho Authorization: Bearer ij_… (ou X-Api-Token). Cada token só enxerga os eventos da conta em que foi criado. Use um token por sistema (um para a catraca, outro para o CRM): assim você revoga um sem parar os outros, e o painel mostra o último uso de cada um.

curl "https://api.ingressoja.com/v1/events?status=published&from=2026-11-01" \
  -H "Authorization: Bearer SEU_TOKEN"

Objeto

Evento

Um evento da sua conta. Em "Buscar evento" vem também a lista sectors.

CampoTipoDescrição
idstringCódigo público do evento, o número do link (ingressoja.com/eventos/89646811269). É o {id} das rotas.
internal_idstring (uuid)Id interno. Também é aceito no lugar de id nas rotas.
namestringNome do evento.
subtitlestring | nullSubtítulo (turnê, edição, atração de abertura).
categorystring | nullCategoria mostrada no site (Show, Festa, Teatro…).
kind"single" | "festival"single = uma data; festival = vários dias, listados em sessions.
status"draft" | "upcoming" | "published" | "cancelled"draft = rascunho; upcoming = divulgado, vendas ainda não abertas; published = à venda; cancelled = cancelado.
sales_pausedbooleantrue quando o organizador pausou as vendas.
starts_atstring (ISO 8601) | nullInício, em UTC. null quando a data ainda não foi definida.
ends_atstring | nullTérmino previsto, em UTC.
gates_open_atstring | nullAbertura dos portões, em UTC.
sales_start_atstring | nullQuando as vendas abrem (eventos upcoming).
timezonestringSempre "America/Sao_Paulo": converta as datas para mostrar no horário local.
age_ratingstring | nullClassificação indicativa ("L", "14", "16", "18").
image_urlstring | nullBanner do evento.
urlstringPágina de venda do evento.
venueobjectLocal: name, city, state e address (street, number, district, zip_code), ou address null quando o endereço não é público.
sessionsarrayDias do festival: id, title, starts_at, gates_open_at. Vazio em eventos de uma data.
sectorsarraySó em "Buscar evento": os setores e tipos de ingresso (veja Setor).
created_at / updated_atstringCriação e última alteração, em UTC.

Objeto

Setor

Um tipo de ingresso à venda (Pista Inteira, Pista Meia, Camarote…). Vem em sectors de "Buscar evento".

CampoTipoDescrição
idstring (uuid)Id do setor. Use em sector_id para filtrar ingressos.
namestringNome do ingresso. Com ingressos avançados é o tipo ("Inteira", "Meia-entrada").
groupstring | nullÁrea a que o tipo pertence ("Pista"). null no modo simples.
kind"full" | "half" | "other"full = inteira; half = meia-entrada (pede comprovante na entrada); other = cortesia, promocional etc.
session_idstring | nullFestival: o dia (id em sessions) em que o ingresso vale.
passportbooleanFestival: true quando vale para todos os dias (entra uma vez por dia).
priceintegerPreço atual em centavos (8000 = R$ 80,00), sem a taxa de serviço.
capacityintegerTotal de lugares do setor.
soldintegerIngressos vendidos (pedidos pagos).
availableintegerLugares ainda livres: capacidade menos vendidos e reservados (pedidos aguardando pagamento).
activebooleanfalse quando o setor foi desativado e não aparece na venda.

Objeto

Pedido

Uma compra. Em "Buscar pedido" e nos webhooks vem também a lista tickets.

CampoTipoDescrição
idstring (uuid)Id do pedido.
numberstringNúmero curto, o que o cliente vê no e-mail (8 primeiros caracteres do id).
event_idstringCódigo do evento.
status"pending" | "paid" | "expired" | "cancelled" | "refunded"pending = aguardando pagamento; paid = pago, ingressos emitidos; expired = o tempo para pagar acabou; cancelled = cancelado; refunded = estornado ou contestado.
channel"online" | "pdv"online = site ou app; pdv = bilheteria física.
payment_methodstring | nullOnline: pix, card ou wallet (Apple Pay / Google Pay). Bilheteria: cash, debit, credit, pix ou courtesy.
installmentsinteger | nullParcelas no cartão.
created_at / paid_at / cancelled_atstring | nullDatas em UTC.
buyerobjectComprador: name, email, phone. Na bilheteria podem vir null.
itemsarraysector_id, sector (nome completo), batch (lote), quantity, unit_price (centavos) e tickets_per_unit (mesa de 4 = 4).
tickets_countintegerQuantos ingressos o pedido gerou.
amountsobjectEm centavos: tickets (valor dos ingressos), discount (cupom), service_fee, service_fee_payer ("customer" ou "organizer"), charged (o que o cliente pagou) e organizer_net (o que fica para você).
couponstring | nullCódigo do cupom usado.
promoter_idstring | nullPromoter do link pelo qual a venda veio.
utmobject | nullOrigem da venda: source, medium, campaign, content, term (e o clique do anúncio, quando houver).

Objeto

Ingresso

Um ingresso emitido (um participante).

CampoTipoDescrição
idstring (uuid)Id do ingresso.
codestringCódigo do ingresso: é o conteúdo do QR code. Use no check-in.
event_id / order_idstringEvento e pedido do ingresso.
status"valid" | "used" | "cancelled"valid = ainda não entrou; used = entrada feita; cancelled = cancelado (estorno, cancelamento).
sector_id / sectorstringSetor e o nome completo dele ("Pista · Inteira").
half_pricebooleantrue para meia-entrada: confira o documento na entrada.
spotstring | nullLugar marcado (mesa, cadeira), quando o setor tem.
holder_namestring | nullNome no ingresso (ou do comprador).
buyer_emailstring | nullE-mail de quem comprou.
used_at / used_bystring | nullQuando e por quem a entrada foi feita (nome do leitor da portaria ou "API: nome do token").
created_atstringEmissão, em UTC.

API de eventos e ingressos

Endpoints

Base: https://api.ingressoja.com/v1

Listar eventos

GET/eventspermissão: leiturapaginado

Eventos da sua conta, do mais próximo para o mais distante. Para os setores de cada evento, use "Buscar evento".

statusstringquery

Situação do evento.

publishedupcomingdraftcancelled
fromstringquery

Só eventos que começam a partir desta data (AAAA-MM-DD, no horário de Brasília, ou ISO 8601).

limitintegerquery

Itens por página, de 1 a 200. Padrão: 50.

cursorstringquery

O pagination.next_cursor da página anterior.

curl "https://api.ingressoja.com/v1/events?status=published&from=2026-11-01" \
  -H "Authorization: Bearer SEU_TOKEN"
Resposta 200
{
  "data": [
    {
      "id": "89646811269",
      "internal_id": "6a1f2c9e-0b5d-4e2a-9c41-3f8e7d2b1a90",
      "name": "Danilo & Davi",
      "subtitle": "Turnê Coração Sertanejo",
      "category": "Show",
      "kind": "single",
      "status": "published",
      "sales_paused": false,
      "starts_at": "2026-11-07T01:00:00.000Z",
      "ends_at": "2026-11-07T06:00:00.000Z",
      "gates_open_at": "2026-11-06T23:00:00.000Z",
      "sales_start_at": null,
      "timezone": "America/Sao_Paulo",
      "age_rating": "18",
      "image_url": "https://ingressoja.com/s3/ingressoja/public/eventos/danilo-e-davi.webp",
      "url": "https://ingressoja.com/eventos/89646811269",
      "venue": {
        "name": "Villa Country",
        "city": "São Paulo",
        "state": "SP",
        "address": {
          "street": "Av. Francisco Matarazzo",
          "number": "774",
          "district": "Barra Funda",
          "zip_code": "05001100"
        }
      },
      "sessions": [],
      "created_at": "2026-10-17T23:51:10.000Z",
      "updated_at": "2026-10-18T14:02:44.000Z"
    }
  ],
  "pagination": {
    "limit": 50,
    "has_more": true,
    "next_cursor": "4a088077-e3c4-4fff-a87a-2fa706b36664"
  }
}

Buscar evento

GET/events/{id}permissão: leitura

Um evento com os setores, preços (em centavos), vendidos e disponíveis. Festivais trazem os dias em sessions.

idstringcaminhoobrigatório

Código do evento (o número do link: ingressoja.com/eventos/89646811269).

curl "https://api.ingressoja.com/v1/events/89646811269" \
  -H "Authorization: Bearer SEU_TOKEN"
Resposta 200
{
  "data": {
    "id": "89646811269",
    "internal_id": "6a1f2c9e-0b5d-4e2a-9c41-3f8e7d2b1a90",
    "name": "Danilo & Davi",
    "subtitle": "Turnê Coração Sertanejo",
    "category": "Show",
    "kind": "single",
    "status": "published",
    "sales_paused": false,
    "starts_at": "2026-11-07T01:00:00.000Z",
    "ends_at": "2026-11-07T06:00:00.000Z",
    "gates_open_at": "2026-11-06T23:00:00.000Z",
    "sales_start_at": null,
    "timezone": "America/Sao_Paulo",
    "age_rating": "18",
    "image_url": "https://ingressoja.com/s3/ingressoja/public/eventos/danilo-e-davi.webp",
    "url": "https://ingressoja.com/eventos/89646811269",
    "venue": {
      "name": "Villa Country",
      "city": "São Paulo",
      "state": "SP",
      "address": {
        "street": "Av. Francisco Matarazzo",
        "number": "774",
        "district": "Barra Funda",
        "zip_code": "05001100"
      }
    },
    "sessions": [],
    "created_at": "2026-10-17T23:51:10.000Z",
    "updated_at": "2026-10-18T14:02:44.000Z",
    "sectors": [
      {
        "id": "b2f0c0aa-1c2d-4e5f-8a9b-0c1d2e3f4a5b",
        "name": "Inteira",
        "group": "Pista",
        "kind": "full",
        "session_id": null,
        "passport": false,
        "price": 8000,
        "capacity": 2000,
        "sold": 812,
        "available": 1170,
        "active": true
      },
      {
        "id": "c3a1d1bb-2d3e-4f60-9bac-1d2e3f4a5b6c",
        "name": "Meia-entrada",
        "group": "Pista",
        "kind": "half",
        "session_id": null,
        "passport": false,
        "price": 4000,
        "capacity": 500,
        "sold": 203,
        "available": 290,
        "active": true
      },
      {
        "id": "d4b2e2cc-3e4f-4071-8cbd-2e3f4a5b6c7d",
        "name": "Camarote Villa",
        "group": null,
        "kind": "full",
        "session_id": null,
        "passport": false,
        "price": 22000,
        "capacity": 300,
        "sold": 214,
        "available": 80,
        "active": true
      }
    ]
  }
}

Listar pedidos

GET/events/{id}/orderspermissão: leiturapaginado

Pedidos do evento, do mais recente para o mais antigo, com comprador, itens, valores e origem (UTM).

idstringcaminhoobrigatório

Código do evento (o número do link: ingressoja.com/eventos/89646811269).

statusstringquery

Situação do pedido.

paidpendingcancelledrefundedexpired
emailstringquery

Só pedidos deste e-mail de comprador.

fromstringquery

Pedidos feitos a partir desta data.

tostringquery

Pedidos feitos até esta data.

limitintegerquery

Itens por página, de 1 a 200. Padrão: 50.

cursorstringquery

O pagination.next_cursor da página anterior.

curl "https://api.ingressoja.com/v1/events/89646811269/orders?status=paid&limit=100" \
  -H "Authorization: Bearer SEU_TOKEN"
Resposta 200
{
  "data": [
    {
      "id": "7d2c1b0a-9e8f-4a7b-b6c5-d4e3f2a1b0c9",
      "number": "7D2C1B0A",
      "event_id": "89646811269",
      "status": "paid",
      "channel": "online",
      "payment_method": "pix",
      "installments": null,
      "created_at": "2026-10-18T15:18:40.000Z",
      "paid_at": "2026-10-18T15:20:03.000Z",
      "cancelled_at": null,
      "buyer": {
        "name": "Maria Souza",
        "email": "maria.souza@gmail.com",
        "phone": "(11) 98765-4321"
      },
      "items": [
        {
          "sector_id": "b2f0c0aa-1c2d-4e5f-8a9b-0c1d2e3f4a5b",
          "sector": "Pista · Inteira",
          "batch": "2º lote",
          "quantity": 2,
          "unit_price": 8000,
          "tickets_per_unit": 1
        }
      ],
      "tickets_count": 2,
      "amounts": {
        "tickets": 16000,
        "discount": 0,
        "service_fee": 1600,
        "service_fee_payer": "customer",
        "charged": 17600,
        "organizer_net": 16000
      },
      "coupon": null,
      "promoter_id": null,
      "utm": {
        "source": "instagram",
        "medium": "bio",
        "campaign": "lancamento"
      }
    }
  ],
  "pagination": {
    "limit": 50,
    "has_more": true,
    "next_cursor": "4a088077-e3c4-4fff-a87a-2fa706b36664"
  }
}

Buscar pedido

GET/events/{id}/orders/{orderId}permissão: leitura

Um pedido com todos os ingressos emitidos.

idstringcaminhoobrigatório

Código do evento (o número do link: ingressoja.com/eventos/89646811269).

orderIdstringcaminhoobrigatório

Id do pedido.

curl "https://api.ingressoja.com/v1/events/89646811269/orders/7d2c1b0a-9e8f-4a7b-b6c5-d4e3f2a1b0c9" \
  -H "Authorization: Bearer SEU_TOKEN"
Resposta 200
{
  "data": {
    "id": "7d2c1b0a-9e8f-4a7b-b6c5-d4e3f2a1b0c9",
    "number": "7D2C1B0A",
    "event_id": "89646811269",
    "status": "paid",
    "channel": "online",
    "payment_method": "pix",
    "installments": null,
    "created_at": "2026-10-18T15:18:40.000Z",
    "paid_at": "2026-10-18T15:20:03.000Z",
    "cancelled_at": null,
    "buyer": {
      "name": "Maria Souza",
      "email": "maria.souza@gmail.com",
      "phone": "(11) 98765-4321"
    },
    "items": [
      {
        "sector_id": "b2f0c0aa-1c2d-4e5f-8a9b-0c1d2e3f4a5b",
        "sector": "Pista · Inteira",
        "batch": "2º lote",
        "quantity": 2,
        "unit_price": 8000,
        "tickets_per_unit": 1
      }
    ],
    "tickets_count": 2,
    "amounts": {
      "tickets": 16000,
      "discount": 0,
      "service_fee": 1600,
      "service_fee_payer": "customer",
      "charged": 17600,
      "organizer_net": 16000
    },
    "coupon": null,
    "promoter_id": null,
    "utm": {
      "source": "instagram",
      "medium": "bio",
      "campaign": "lancamento"
    },
    "tickets": [
      {
        "id": "0f3e2d1c-4b5a-6978-8a9b-0c1d2e3f4a5b",
        "code": "IJ7K2M9QX4",
        "event_id": "89646811269",
        "order_id": "7d2c1b0a-9e8f-4a7b-b6c5-d4e3f2a1b0c9",
        "status": "valid",
        "sector_id": "b2f0c0aa-1c2d-4e5f-8a9b-0c1d2e3f4a5b",
        "sector": "Pista · Inteira",
        "half_price": false,
        "spot": null,
        "holder_name": "Maria Souza",
        "buyer_email": "maria.souza@gmail.com",
        "used_at": null,
        "used_by": null,
        "created_at": "2026-10-18T15:20:04.000Z"
      },
      {
        "id": "1a4f3e2d-5c6b-4a89-9bac-1d2e3f4a5b6c",
        "code": "IJQ8R3T6W1",
        "event_id": "89646811269",
        "order_id": "7d2c1b0a-9e8f-4a7b-b6c5-d4e3f2a1b0c9",
        "status": "valid",
        "sector_id": "b2f0c0aa-1c2d-4e5f-8a9b-0c1d2e3f4a5b",
        "sector": "Pista · Inteira",
        "half_price": false,
        "spot": null,
        "holder_name": "João Souza",
        "buyer_email": "maria.souza@gmail.com",
        "used_at": null,
        "used_by": null,
        "created_at": "2026-10-18T15:20:04.000Z"
      }
    ]
  }
}

Listar ingressos

GET/events/{id}/ticketspermissão: leiturapaginado

Ingressos emitidos (a lista de participantes) do evento, na ordem de emissão.

idstringcaminhoobrigatório

Código do evento (o número do link: ingressoja.com/eventos/89646811269).

statusstringquery

Situação do ingresso.

validusedcancelled
emailstringquery

E-mail do comprador.

sector_idstringquery

Só ingressos deste setor.

order_idstringquery

Só ingressos deste pedido.

limitintegerquery

Itens por página, de 1 a 200. Padrão: 50.

cursorstringquery

O pagination.next_cursor da página anterior.

curl "https://api.ingressoja.com/v1/events/89646811269/tickets?status=valid&limit=200" \
  -H "Authorization: Bearer SEU_TOKEN"
Resposta 200
{
  "data": [
    {
      "id": "0f3e2d1c-4b5a-6978-8a9b-0c1d2e3f4a5b",
      "code": "IJ7K2M9QX4",
      "event_id": "89646811269",
      "order_id": "7d2c1b0a-9e8f-4a7b-b6c5-d4e3f2a1b0c9",
      "status": "valid",
      "sector_id": "b2f0c0aa-1c2d-4e5f-8a9b-0c1d2e3f4a5b",
      "sector": "Pista · Inteira",
      "half_price": false,
      "spot": null,
      "holder_name": "Maria Souza",
      "buyer_email": "maria.souza@gmail.com",
      "used_at": null,
      "used_by": null,
      "created_at": "2026-10-18T15:20:04.000Z"
    }
  ],
  "pagination": {
    "limit": 50,
    "has_more": true,
    "next_cursor": "4a088077-e3c4-4fff-a87a-2fa706b36664"
  }
}

Buscar ingresso

GET/events/{id}/tickets/{code}permissão: leitura

Um ingresso pelo código (o mesmo conteúdo do QR code).

idstringcaminhoobrigatório

Código do evento (o número do link: ingressoja.com/eventos/89646811269).

codestringcaminhoobrigatório

Código do ingresso.

curl "https://api.ingressoja.com/v1/events/89646811269/tickets/IJ7K2M9QX4" \
  -H "Authorization: Bearer SEU_TOKEN"
Resposta 200
{
  "data": {
    "id": "0f3e2d1c-4b5a-6978-8a9b-0c1d2e3f4a5b",
    "code": "IJ7K2M9QX4",
    "event_id": "89646811269",
    "order_id": "7d2c1b0a-9e8f-4a7b-b6c5-d4e3f2a1b0c9",
    "status": "valid",
    "sector_id": "b2f0c0aa-1c2d-4e5f-8a9b-0c1d2e3f4a5b",
    "sector": "Pista · Inteira",
    "half_price": false,
    "spot": null,
    "holder_name": "Maria Souza",
    "buyer_email": "maria.souza@gmail.com",
    "used_at": null,
    "used_by": null,
    "created_at": "2026-10-18T15:20:04.000Z"
  }
}

Fazer check-in

POST/events/{id}/tickets/{code}/check-inpermissão: check-in

Valida o ingresso na entrada (catraca, totem, app próprio). Segue a mesma regra da portaria do IngressoJá: libera uma única vez, e a leitura repetida volta "used". Sempre responde 200 quando o ingresso foi lido; o resultado está em data.result.

idstringcaminhoobrigatório

Código do evento (o número do link: ingressoja.com/eventos/89646811269).

codestringcaminhoobrigatório

Código lido no QR code.

session_idstringcorpo

Festival: o dia da entrada (id em sessions). O passaporte entra uma vez por dia.

  • result "ok": entrada liberada.
  • result "used": já entrou. used_at e used_by dizem quando e onde (ex.: "Este ingresso já foi utilizado.").
  • result "invalid": não libere. message explica: "Ingresso não encontrado.", "Este ingresso é de outro evento.", "Ingresso cancelado." ou, em festival, "Este ingresso é de outro dia do festival (…)".
  • Dois leitores com o mesmo ingresso ao mesmo tempo: só um recebe "ok".
curl -X POST "https://api.ingressoja.com/v1/events/89646811269/tickets/IJ7K2M9QX4/check-in" \
  -H "Authorization: Bearer SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
Resposta 200
{
  "data": {
    "result": "ok",
    "message": "Entrada liberada.",
    "code": "IJ7K2M9QX4",
    "sector": "Pista · Inteira",
    "half_price": false,
    "holder_name": "Maria Souza",
    "used_at": null,
    "used_by": null
  }
}
data.resultSignificaO que fazer
okEntrada liberada.Abra a catraca.
usedO ingresso já entrou (used_at, used_by).Não libere; mostre quando e onde entrou.
invalidNão encontrado, de outro evento ou dia, ou cancelado.Não libere; mostre data.message.

API de eventos e ingressos

Webhooks: avisos em tempo real

Cadastre o endereço https do seu sistema em Integrações › Webhooks, escolha os avisos e, se quiser, só alguns eventos. Cada aviso chega como POST com JSON { id, type, created_at, data }.

Responda com qualquer status 2xx em até 10 segundos. Se o seu sistema estiver fora, tentamos de novo depois de 1, 5, 30, 120, 360 minutos. No painel dá para ver cada entrega e reenviar.

typeQuandoEm data
order.paidO pagamento foi aprovado e os ingressos foram emitidos (site, app ou bilheteria).event + order (com tickets)
order.refundedO pagamento foi devolvido ou contestado; os ingressos válidos foram cancelados.event + order (com tickets)
order.cancelledUma venda paga foi cancelada (por exemplo, na bilheteria).event + order (com tickets)
ticket.checked_inEntrada liberada na portaria, no painel ou pela API.event + ticket + check_in { at, by, session_id }
event.updatedO evento foi salvo, ou as vendas foram pausadas ou retomadas.event (com sectors)
pingBotão "Enviar teste" no painel.{ message }

Cabeçalhos: X-IngressoJa-Event (o tipo), X-IngressoJa-Delivery (id único da entrega, para ignorar repetidos) e X-IngressoJa-Signature.

order.paid
{
  "id": "5b9c1e2f-3a4d-4e6f-8a7b-9c0d1e2f3a4b",
  "type": "order.paid",
  "created_at": "2026-10-18T15:20:04.000Z",
  "data": {
    "event": {
      "id": "89646811269",
      "internal_id": "6a1f2c9e-0b5d-4e2a-9c41-3f8e7d2b1a90",
      "name": "Danilo & Davi",
      "subtitle": "Turnê Coração Sertanejo",
      "category": "Show",
      "kind": "single",
      "status": "published",
      "sales_paused": false,
      "starts_at": "2026-11-07T01:00:00.000Z",
      "ends_at": "2026-11-07T06:00:00.000Z",
      "gates_open_at": "2026-11-06T23:00:00.000Z",
      "sales_start_at": null,
      "timezone": "America/Sao_Paulo",
      "age_rating": "18",
      "image_url": "https://ingressoja.com/s3/ingressoja/public/eventos/danilo-e-davi.webp",
      "url": "https://ingressoja.com/eventos/89646811269",
      "venue": {
        "name": "Villa Country",
        "city": "São Paulo",
        "state": "SP",
        "address": {
          "street": "Av. Francisco Matarazzo",
          "number": "774",
          "district": "Barra Funda",
          "zip_code": "05001100"
        }
      },
      "sessions": [],
      "created_at": "2026-10-17T23:51:10.000Z",
      "updated_at": "2026-10-18T14:02:44.000Z"
    },
    "order": {
      "id": "7d2c1b0a-9e8f-4a7b-b6c5-d4e3f2a1b0c9",
      "number": "7D2C1B0A",
      "event_id": "89646811269",
      "status": "paid",
      "channel": "online",
      "payment_method": "pix",
      "installments": null,
      "created_at": "2026-10-18T15:18:40.000Z",
      "paid_at": "2026-10-18T15:20:03.000Z",
      "cancelled_at": null,
      "buyer": {
        "name": "Maria Souza",
        "email": "maria.souza@gmail.com",
        "phone": "(11) 98765-4321"
      },
      "items": [
        {
          "sector_id": "b2f0c0aa-1c2d-4e5f-8a9b-0c1d2e3f4a5b",
          "sector": "Pista · Inteira",
          "batch": "2º lote",
          "quantity": 2,
          "unit_price": 8000,
          "tickets_per_unit": 1
        }
      ],
      "tickets_count": 2,
      "amounts": {
        "tickets": 16000,
        "discount": 0,
        "service_fee": 1600,
        "service_fee_payer": "customer",
        "charged": 17600,
        "organizer_net": 16000
      },
      "coupon": null,
      "promoter_id": null,
      "utm": {
        "source": "instagram",
        "medium": "bio",
        "campaign": "lancamento"
      },
      "tickets": [
        {
          "id": "0f3e2d1c-4b5a-6978-8a9b-0c1d2e3f4a5b",
          "code": "IJ7K2M9QX4",
          "event_id": "89646811269",
          "order_id": "7d2c1b0a-9e8f-4a7b-b6c5-d4e3f2a1b0c9",
          "status": "valid",
          "sector_id": "b2f0c0aa-1c2d-4e5f-8a9b-0c1d2e3f4a5b",
          "sector": "Pista · Inteira",
          "half_price": false,
          "spot": null,
          "holder_name": "Maria Souza",
          "buyer_email": "maria.souza@gmail.com",
          "used_at": null,
          "used_by": null,
          "created_at": "2026-10-18T15:20:04.000Z"
        }
      ]
    }
  }
}
ticket.checked_in
{
  "id": "8e1d2c3b-4a5f-4e6d-9c8b-7a6f5e4d3c2b",
  "type": "ticket.checked_in",
  "created_at": "2026-11-06T23:41:12.000Z",
  "data": {
    "event": {
      "id": "89646811269",
      "internal_id": "6a1f2c9e-0b5d-4e2a-9c41-3f8e7d2b1a90",
      "name": "Danilo & Davi",
      "subtitle": "Turnê Coração Sertanejo",
      "category": "Show",
      "kind": "single",
      "status": "published",
      "sales_paused": false,
      "starts_at": "2026-11-07T01:00:00.000Z",
      "ends_at": "2026-11-07T06:00:00.000Z",
      "gates_open_at": "2026-11-06T23:00:00.000Z",
      "sales_start_at": null,
      "timezone": "America/Sao_Paulo",
      "age_rating": "18",
      "image_url": "https://ingressoja.com/s3/ingressoja/public/eventos/danilo-e-davi.webp",
      "url": "https://ingressoja.com/eventos/89646811269",
      "venue": {
        "name": "Villa Country",
        "city": "São Paulo",
        "state": "SP",
        "address": {
          "street": "Av. Francisco Matarazzo",
          "number": "774",
          "district": "Barra Funda",
          "zip_code": "05001100"
        }
      },
      "sessions": [],
      "created_at": "2026-10-17T23:51:10.000Z",
      "updated_at": "2026-10-18T14:02:44.000Z"
    },
    "ticket": {
      "id": "0f3e2d1c-4b5a-6978-8a9b-0c1d2e3f4a5b",
      "code": "IJ7K2M9QX4",
      "event_id": "89646811269",
      "order_id": "7d2c1b0a-9e8f-4a7b-b6c5-d4e3f2a1b0c9",
      "status": "used",
      "sector_id": "b2f0c0aa-1c2d-4e5f-8a9b-0c1d2e3f4a5b",
      "sector": "Pista · Inteira",
      "half_price": false,
      "spot": null,
      "holder_name": "Maria Souza",
      "buyer_email": "maria.souza@gmail.com",
      "used_at": "2026-11-06T23:41:12.000Z",
      "used_by": "Portão A",
      "created_at": "2026-10-18T15:20:04.000Z"
    },
    "check_in": {
      "at": "2026-11-06T23:41:12.000Z",
      "by": "Portão A",
      "session_id": null
    }
  }
}

Webhooks de eventos

Conferir a assinatura

Ao criar o webhook, o painel mostra um segredo (whsec_…). Cada aviso traz X-IngressoJa-Signature: t=1760800804,v1=5f2a…, em que v1 é o HMAC-SHA256, em hexadecimal, de <t>.<corpo> com o segredo. Confira antes de confiar no conteúdo, use o corpo exatamente como chegou e recuse t de mais de 5 minutos.

const crypto = require('crypto')

// rawBody = o corpo exatamente como chegou (texto, antes do JSON.parse)
function webhookValido(headerAssinatura, rawBody, segredo) {
  const partes = Object.fromEntries(headerAssinatura.split(',').map((p) => p.split('=')))
  const esperado = crypto.createHmac('sha256', segredo).update(partes.t + '.' + rawBody).digest('hex')
  const recente = Math.abs(Date.now() / 1000 - Number(partes.t)) < 300 // até 5 minutos
  return recente && crypto.timingSafeEqual(Buffer.from(partes.v1), Buffer.from(esperado))
}

API de pagamentos (PIX)

Como funciona

Para o parceiro que já tem o próprio sistema (loja, plataforma, app) e quer receber por PIX pelo IngressoJá. O valor pago entra no saldo da sua conta no IngressoJá, com a taxa e o prazo de recebimento da conta, e você saca pelo painel.

  1. 1

    Pedido

    O cliente fecha o pedido no seu sistema.

  2. 2

    Gerar PIX

    Seu servidor chama a API com o identifier do pedido.

  3. 3

    Mostrar

    Você mostra o copia e cola e o QR code.

  4. 4

    Aviso

    Pagou: chega TRANSACTION_PAID no seu callbackUrl.

  5. 5

    Liberar

    Confere a assinatura e libera o pedido.

Enquanto o cliente espera na tela do PIX, você também pode consultar a cobrança a cada 5 a 10 segundos (Consultar transação) e liberar assim que vier COMPLETED. O aviso continua sendo o caminho principal.

API de pagamentos (PIX)

Chaves de acesso

No painel, abra o menu API: lá estão a chave pública e a chave privada da conta. Envie as duas em toda chamada, nos cabeçalhos x-public-key e x-secret-key. A chave privada também assina os avisos de pagamento: guarde como uma senha.

curl "https://api.ingressoja.com/v1/transactions?identifier=PED-2026-000187" \
  -H "x-public-key: SUA_CHAVE_PUBLICA" \
  -H "x-secret-key: SUA_CHAVE_PRIVADA"

API de pagamentos (PIX)

Cobranças

Gerar PIX

POST/gateway/pix/receive

Gera uma cobrança PIX em nome da sua conta: devolve o copia e cola e o QR code para você mostrar ao pagador. O valor pago entra no seu saldo no IngressoJá, com a taxa e o prazo de recebimento da sua conta.

x-public-keystringcabeçalhoobrigatório

Chave pública (painel › API).

x-secret-keystringcabeçalhoobrigatório

Chave privada (painel › API). Só no seu servidor.

identifierstringcorpoobrigatório

O id do pedido no seu sistema. Único por conta: um segundo PIX com o mesmo identifier volta 409. É ele que volta no aviso de pagamento.

amountnumbercorpoobrigatório

Valor em reais, com até 2 casas (89.9 = R$ 89,90).

client.namestringcorpoobrigatório

Nome do pagador.

client.emailstringcorpoobrigatório

E-mail do pagador.

client.documentstringcorpoobrigatório

CPF ou CNPJ válido, com ou sem pontuação.

client.phonestringcorpo

Celular com DDD.

productsarraycorpo

Itens: name, quantity e price (em reais). O nome do primeiro aparece na cobrança.

dueDatestringcorpo

Vencimento do PIX em ISO 8601 (2026-11-05T23:59:00-03:00). Padrão: 24 horas. Mínimo 5 minutos, máximo 30 dias.

callbackUrlstringcorpo

Endereço https que recebe o aviso de pagamento desta cobrança (veja Avisos de pagamento).

metadataobjectcorpo

Dados seus (até alguns campos simples). Voltam no aviso, em trackProps.

  • Guarde transactionId junto do seu pedido: é por ele (ou pelo identifier) que você consulta a cobrança.
  • Mostre pix.code com um botão "Copiar" e pix.image como QR code (<img src="…">). pix.base64 é a mesma imagem sem o prefixo data:.
  • order.url é reservado (sempre null por enquanto): a tela de pagamento é a sua.
curl -X POST "https://api.ingressoja.com/v1/gateway/pix/receive" \
  -H "x-public-key: SUA_CHAVE_PUBLICA" \
  -H "x-secret-key: SUA_CHAVE_PRIVADA" \
  -H "Content-Type: application/json" \
  -d '{
  "identifier": "PED-2026-000187",
  "amount": 89.9,
  "client": {
    "name": "Ana Ribeiro",
    "email": "ana.ribeiro@gmail.com",
    "phone": "11987654321",
    "document": "529.982.247-25"
  },
  "products": [
    {
      "id": "plano-anual",
      "name": "Plano anual",
      "quantity": 1,
      "price": 89.9
    }
  ],
  "dueDate": "2026-11-05T23:59:00-03:00",
  "callbackUrl": "https://loja.exemplo.com.br/webhooks/ingressoja",
  "metadata": {
    "pedido_loja": "A-77"
  }
}'
Resposta 200
{
  "transactionId": "PPf8d83fcf20",
  "identifier": "PED-2026-000187",
  "status": "OK",
  "amount": 89.9,
  "expiresAt": "2026-11-06T02:59:00.000Z",
  "order": {
    "id": "PPf8d83fcf20",
    "url": null
  },
  "pix": {
    "code": "00020101021226930014br.gov.bcb.pix2571pix-qr.mercadopago.com/instore/ol/v2/3Z9Kq8vM2xT4bY7nH1cR5wE0aF6dG520400005303986540589.905802BR5911IngressoJa6009SAO PAULO62070503***6304B1F7",
    "base64": "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAQMAAABmvDolAAAABlBMVEX///8AAABVwtN+AAAB…",
    "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAQMAAABmvDolAAAABlBMVEX///8AAABVwtN+AAAB…"
  }
}

Consultar transação

GET/transactions

A situação de uma cobrança pelo id (transactionId) ou pelo identifier que você enviou. Só enxerga as cobranças da sua conta.

x-public-keystringcabeçalhoobrigatório

Chave pública (painel › API).

x-secret-keystringcabeçalhoobrigatório

Chave privada (painel › API). Só no seu servidor.

idstringquery

O transactionId devolvido ao gerar o PIX.

identifierstringquery

O identifier do seu pedido (o nome antigo externalId também é aceito).

curl "https://api.ingressoja.com/v1/transactions?identifier=PED-2026-000187" \
  -H "x-public-key: SUA_CHAVE_PUBLICA" \
  -H "x-secret-key: SUA_CHAVE_PRIVADA"
Resposta 200
{
  "success": true,
  "data": {
    "id": "PPf8d83fcf20",
    "identifier": "PED-2026-000187",
    "externalId": "PED-2026-000187",
    "currency": "BRL",
    "amount": 89.9,
    "chargeAmount": 89.9,
    "exchangeRate": 1,
    "producerExtraAmount": 0,
    "status": "COMPLETED",
    "statusDescription": null,
    "purchaseType": "ONCE",
    "paymentMethod": "PIX",
    "details": "Plano anual",
    "errorDescription": null,
    "webhookUrl": "https://loja.exemplo.com.br/webhooks/ingressoja",
    "availableAt": null,
    "createdAt": "2026-11-04T18:39:19.762Z",
    "expiresAt": "2026-11-06T02:59:00.000Z",
    "refundedAt": null,
    "payedAt": "2026-11-04T18:41:02.846Z",
    "boletoInformation": null,
    "pixInformation": {
      "qrCode": "00020101021226930014br.gov.bcb.pix2571pix-qr.mercadopago.com/instore/ol/v2/3Z9Kq8vM2xT4bY7nH1cR5wE0aF6dG520400005303986540589.905802BR5911IngressoJa6009SAO PAULO62070503***6304B1F7",
      "base64": "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAQMAAABmvDolAAAABlBMVEX///8AAABVwtN+AAAB…",
      "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAQMAAABmvDolAAAABlBMVEX///8AAABVwtN+AAAB…"
    }
  },
  "message": "Transação encontrada com sucesso"
}

API de pagamentos (PIX)

Avisos de pagamento

Mande callbackUrl ao gerar o PIX (um endereço por cobrança) e/ou cadastre um webhook da conta. O aviso chega como POST com JSON. Responda 2xx.

eventtransaction.statusQuando
TRANSACTION_PAIDCOMPLETEDO PIX foi pago e confirmado pelo banco.
TRANSACTION_CANCELEDFAILEDO PIX venceu sem pagamento ou foi cancelado.
TRANSACTION_REFUNDEDREFUNDEDO pagamento foi devolvido.
TRANSACTION_CHARGED_BACKCHARGED_BACKO pagamento foi contestado.
  • transaction.identifier é o identifier que você mandou: use para achar o seu pedido.
  • transaction.amount vem em centavos (texto, "8990") e originalAmount em reais ("89.9"). metadata volta em trackProps.
  • Cabeçalhos: X-Event (o evento) e X-IngressoJa-Signature: sha256=…, o HMAC-SHA256 do corpo com a sua x-secret-key. Nos webhooks cadastrados, o campo token traz o token daquele webhook (no callbackUrl vem vazio).
  • O mesmo aviso pode chegar mais de uma vez: libere o pedido uma vez só.
TRANSACTION_PAID
{
  "event": "TRANSACTION_PAID",
  "token": "",
  "offerCode": "PED-2026-000187",
  "client": {
    "id": "NTI5Ljk4Mi",
    "name": "Ana Ribeiro",
    "email": "ana.ribeiro@gmail.com",
    "cpf": "529.982.247-25",
    "address": null
  },
  "transaction": {
    "id": "PPf8d83fcf20",
    "identifier": "PED-2026-000187",
    "status": "COMPLETED",
    "paymentMethod": "PIX",
    "originalCurrency": "BRL",
    "originalAmount": "89.9",
    "currency": "BRL",
    "amount": "8990",
    "createdAt": "2026-11-04T18:39:19.762Z",
    "payedAt": "2026-11-04T18:41:02.846Z"
  },
  "subscription": null,
  "orderItems": [
    {
      "id": "UFBmOGQ4M2",
      "price": "8990",
      "product": {
        "id": "UGxhbm8gYW",
        "name": "Plano anual",
        "externalId": "PED-2026-000187"
      }
    }
  ],
  "trackProps": {
    "pedido_loja": "A-77"
  }
}
const crypto = require('crypto')

// rawBody = o corpo exatamente como chegou; chavePrivada = a sua x-secret-key
function avisoValido(header, rawBody, chavePrivada) {
  const esperado = 'sha256=' + crypto.createHmac('sha256', chavePrivada).update(rawBody).digest('hex')
  return header?.length === esperado.length && crypto.timingSafeEqual(Buffer.from(header), Buffer.from(esperado))
}

// Express: app.post('/webhooks/ingressoja', express.raw({ type: 'application/json' }), (req, res) => {
//   if (!avisoValido(req.get('X-IngressoJa-Signature'), req.body.toString('utf8'), process.env.INGRESSOJA_SECRET_KEY)) return res.sendStatus(401)
//   const aviso = JSON.parse(req.body)
//   if (aviso.event === 'TRANSACTION_PAID') liberarPedido(aviso.transaction.identifier)
//   res.sendStatus(200)
// })

API de pagamentos (PIX)

Webhooks de pagamento

Opcional: um endereço que recebe os avisos de todas as cobranças da conta, sem mandar callbackUrl em cada PIX.

Cadastrar webhook

POST/webhooks

Um endereço que recebe os avisos de todas as cobranças da conta (sem precisar mandar callbackUrl em cada PIX). Também recebe os avisos das vendas de ingresso da conta.

x-public-keystringcabeçalhoobrigatório

Chave pública (painel › API).

x-secret-keystringcabeçalhoobrigatório

Chave privada (painel › API). Só no seu servidor.

namestringcorpoobrigatório

Nome para você reconhecer.

callbackUrlstringcorpoobrigatório

Endereço https.

eventsarraycorpoobrigatório

Avisos que quer receber.

TRANSACTION_PAIDTRANSACTION_CANCELEDTRANSACTION_REFUNDEDTRANSACTION_CHARGED_BACK
  • Guarde o token: ele vem no campo token de cada aviso deste webhook.
curl -X POST "https://api.ingressoja.com/v1/webhooks" \
  -H "x-public-key: SUA_CHAVE_PUBLICA" \
  -H "x-secret-key: SUA_CHAVE_PRIVADA" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "ERP da loja",
  "callbackUrl": "https://loja.exemplo.com.br/webhooks/ingressoja",
  "events": [
    "TRANSACTION_PAID",
    "TRANSACTION_CANCELED",
    "TRANSACTION_REFUNDED",
    "TRANSACTION_CHARGED_BACK"
  ]
}'
Resposta 201
{
  "id": "3c9a1f52-7d1e-4b0a-a8c2-5e6f7a8b9c0d",
  "name": "ERP da loja",
  "callbackUrl": "https://loja.exemplo.com.br/webhooks/ingressoja",
  "events": [
    "TRANSACTION_PAID",
    "TRANSACTION_CANCELED",
    "TRANSACTION_REFUNDED",
    "TRANSACTION_CHARGED_BACK"
  ],
  "token": "wh_Q2n8Zk1VbT7mR4xY9pLc0aSd",
  "status": "active",
  "allProducts": true,
  "productIds": [],
  "createdAt": "2026-11-04T18:30:00.000Z"
}

Listar webhooks

GET/webhooks

Os webhooks de pagamento cadastrados na sua conta.

x-public-keystringcabeçalhoobrigatório

Chave pública (painel › API).

x-secret-keystringcabeçalhoobrigatório

Chave privada (painel › API). Só no seu servidor.

curl "https://api.ingressoja.com/v1/webhooks" \
  -H "x-public-key: SUA_CHAVE_PUBLICA" \
  -H "x-secret-key: SUA_CHAVE_PRIVADA"
Resposta 200
[
  {
    "id": "3c9a1f52-7d1e-4b0a-a8c2-5e6f7a8b9c0d",
    "name": "ERP da loja",
    "callbackUrl": "https://loja.exemplo.com.br/webhooks/ingressoja",
    "events": [
      "TRANSACTION_PAID",
      "TRANSACTION_CANCELED",
      "TRANSACTION_REFUNDED",
      "TRANSACTION_CHARGED_BACK"
    ],
    "token": "wh_Q2n8Zk1VbT7mR4xY9pLc0aSd",
    "status": "active",
    "allProducts": true,
    "productIds": [],
    "createdAt": "2026-11-04T18:30:00.000Z",
    "updatedAt": "2026-11-04T18:30:00.000Z"
  }
]

Remover webhook

DELETE/webhooks

Remove um webhook de pagamento da sua conta.

x-public-keystringcabeçalhoobrigatório

Chave pública (painel › API).

x-secret-keystringcabeçalhoobrigatório

Chave privada (painel › API). Só no seu servidor.

idstringqueryobrigatório

Id do webhook.

curl -X DELETE "https://api.ingressoja.com/v1/webhooks?id=3c9a1f52-7d1e-4b0a-a8c2-5e6f7a8b9c0d" \
  -H "x-public-key: SUA_CHAVE_PUBLICA" \
  -H "x-secret-key: SUA_CHAVE_PRIVADA"
Resposta 200
{
  "id": "3c9a1f52-7d1e-4b0a-a8c2-5e6f7a8b9c0d",
  "deleted": true
}

API de pagamentos (PIX)

Situações e erros

statusSignifica
PENDINGPIX gerado, aguardando o pagamento.
COMPLETEDPago. Libere o pedido.
FAILEDVenceu sem pagamento ou foi cancelado. Gere outro PIX (com outro identifier) se o cliente quiser pagar.
REFUNDEDPagamento devolvido ao pagador.
CHARGED_BACKPagamento contestado.
StatuserrorCodeQuando
400VALIDATION_ERROR / INVALID_JSONCampo faltando ou inválido; details.field diz qual (ex.: customer.document).
401MISSING_HEADERSFaltou x-public-key ou x-secret-key.
403INVALID_CREDENTIALSChaves erradas.
404TRANSACTION_NOT_FOUNDCobrança não existe ou não é da sua conta.
409DUPLICATE_IDENTIFIERJá existe uma cobrança com este identifier.
502ACQUIRER_ERRORO banco não gerou o PIX agora. Tente de novo em instantes (com o mesmo identifier).
503NO_ACQUIRER_AVAILABLEA conta ainda não está liberada para receber. Fale com o suporte.

Guia

Catraca e check-in

Crie um token só com a permissão check-in para cada catraca ou leitor. Leia o QR code (o conteúdo é o code do ingresso) e chame Fazer check-in. A regra é a mesma da portaria do IngressoJá: um ingresso só entra uma vez, mesmo lido em dois aparelhos ao mesmo tempo, e a entrada aparece no painel na hora.

Node.js
// Catraca: lê o QR code e decide se abre
async function validarEntrada(eventoId, codigoLido) {
  const resposta = await fetch(`https://api.ingressoja.com/v1/events/${eventoId}/tickets/${encodeURIComponent(codigoLido)}/check-in`, {
    method: 'POST',
    headers: { Authorization: `Bearer ${process.env.INGRESSOJA_TOKEN_CATRACA}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({}), // festival: { session_id: 'id do dia' }
  })
  const { data } = await resposta.json()
  if (data.result === 'ok') return abrirCatraca(data.half_price ? 'Conferir documento de meia-entrada' : data.holder_name)
  mostrarNoVisor(data.message) // "Este ingresso já foi utilizado." / "Ingresso não encontrado."
}

Guia

Sincronizar vendas (CRM, ERP, planilha)

Faça a carga inicial pela lista de pedidos e, daí em diante, receba as novidades pelo webhook order.paid (e order.refunded para tirar os estornos). Use o id do pedido como chave: o mesmo pedido pode chegar mais de uma vez.

Node.js
// Node.js 18+: todos os pedidos pagos de um evento, página por página
async function pedidosPagos(eventoId) {
  const pedidos = []
  let cursor = null
  do {
    const url = new URL(`https://api.ingressoja.com/v1/events/${eventoId}/orders`)
    url.searchParams.set('status', 'paid')
    url.searchParams.set('limit', '200')
    if (cursor) url.searchParams.set('cursor', cursor)
    const resposta = await fetch(url, { headers: { Authorization: `Bearer ${process.env.INGRESSOJA_TOKEN}` } })
    if (resposta.status === 429) { await new Promise((r) => setTimeout(r, 2000)); continue }
    const { data, pagination } = await resposta.json()
    pedidos.push(...data)
    cursor = pagination.has_more ? pagination.next_cursor : null
  } while (cursor)
  return pedidos
}

Guia

Loja recebendo por PIX

O fluxo completo de uma loja que usa o IngressoJá como gateway: gerar o PIX no checkout e liberar o pedido quando o aviso chegar.

Node.js
// Loja (Node.js + Express): fechar o pedido com PIX e liberar quando pagar
app.post('/checkout/pix', async (req, res) => {
  const pedido = await criarPedido(req.body) // no seu banco
  const resposta = await fetch('https://api.ingressoja.com/v1/gateway/pix/receive', {
    method: 'POST',
    headers: {
      'x-public-key': process.env.INGRESSOJA_PUBLIC_KEY,
      'x-secret-key': process.env.INGRESSOJA_SECRET_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      identifier: pedido.id,
      amount: pedido.total, // em reais: 89.9
      client: { name: pedido.nome, email: pedido.email, document: pedido.cpf, phone: pedido.celular },
      products: [{ name: pedido.descricao, quantity: 1, price: pedido.total }],
      callbackUrl: 'https://loja.exemplo.com.br/webhooks/ingressoja',
    }),
  })
  const pix = await resposta.json()
  if (!resposta.ok) return res.status(400).json({ erro: pix.message })
  await salvarCobranca(pedido.id, pix.transactionId)
  res.json({ copiaECola: pix.pix.code, qrCode: pix.pix.image, venceEm: pix.expiresAt })
})

// o aviso: confere a assinatura e libera uma vez só
app.post('/webhooks/ingressoja', express.raw({ type: 'application/json' }), async (req, res) => {
  const corpo = req.body.toString('utf8')
  const esperado = 'sha256=' + crypto.createHmac('sha256', process.env.INGRESSOJA_SECRET_KEY).update(corpo).digest('hex')
  if (req.get('X-IngressoJa-Signature') !== esperado) return res.sendStatus(401)
  const aviso = JSON.parse(corpo)
  if (aviso.event === 'TRANSACTION_PAID') await liberarPedidoSeAindaNaoLiberado(aviso.transaction.identifier)
  res.sendStatus(200)
})
Gerar PIX em outras linguagens
curl -X POST "https://api.ingressoja.com/v1/gateway/pix/receive" \
  -H "x-public-key: SUA_CHAVE_PUBLICA" \
  -H "x-secret-key: SUA_CHAVE_PRIVADA" \
  -H "Content-Type: application/json" \
  -d '{
  "identifier": "PED-2026-000187",
  "amount": 89.9,
  "client": {
    "name": "Ana Ribeiro",
    "email": "ana.ribeiro@gmail.com",
    "phone": "11987654321",
    "document": "529.982.247-25"
  },
  "products": [
    {
      "id": "plano-anual",
      "name": "Plano anual",
      "quantity": 1,
      "price": 89.9
    }
  ],
  "dueDate": "2026-11-05T23:59:00-03:00",
  "callbackUrl": "https://loja.exemplo.com.br/webhooks/ingressoja",
  "metadata": {
    "pedido_loja": "A-77"
  }
}'

Guia

Boas práticas

  • Chame as APIs só do seu servidor. Token e chaves dão acesso aos dados dos seus compradores e ao seu recebimento.
  • Prefira os webhooks a consultar a API a cada poucos segundos: o aviso chega na hora e não gasta o seu limite.
  • Os avisos podem chegar repetidos ou fora de ordem: use o id da entrega (ou o identifier) e a situação atual para não processar duas vezes.
  • Um identifier por pedido. Se o PIX vencer, gere outro com um identifier novo (ex.: PED-187-2).
  • Se Gerar PIX der erro de rede, consulte pelo identifier antes de tentar de novo: a cobrança pode ter sido criada.
  • Dados de compradores são pessoais (LGPD): guarde só o necessário.
  • Dúvidas ou um recurso que falta: contato@ingressoja.com.

Para IA

Documentação para IA

Vai integrar com a ajuda do Claude, do ChatGPT, do Cursor ou de outro assistente? Entregue a documentação inteira em Markdown: ela tem todos os endpoints, campos, exemplos e regras desta página, num texto só.

Abrir no Claude Abrir no ChatGPT
Prompt sugerido
Você vai me ajudar a integrar meu sistema com o IngressoJá.
Leia a documentação completa em https://ingressoja.com/llms-full.txt antes de responder.
Use só os endpoints, campos e formatos que estão nela; se algo não estiver lá, diga que não existe.
Meu sistema é: [descreva: linguagem, framework, o que precisa fazer — ex.: "loja em Laravel que precisa gerar PIX" ou "catraca que valida ingresso"].