SportApi
Documentação da API · versão 1.2.0

Odds, apostas e cupons — documentação técnica da API

Este arquivo contém um script independente mínimo para conexão com o sistema de cálculo de cupom SportAPI. Detalhes e casos raros estão em documentação completa.

Fluxo principal http
POST /api/partner/login
POST /api/partner/coupons/place
GET  /api/partner/coupons/calculated?time=10

1. O que você precisa obter do gerente

  • API de URL base;
  • login e senha da conta do cliente;
  • ao usar retorno de chamada - habilite a função e a frase secreta callback_secret.

Os exemplos usam um endereço condicional:

BASE_URL="https://coupon-api.example.com"

Na produção, use HTTPS. Todas as datas são transmitidas como carimbo de data/hora Unix em milissegundos e os valores monetários são transmitidos como números decimais sem precisão fixa.

2. Formato de resposta da API

Sucesso:

{
  "code": 1,
  "body": {},
  "error_code": null,
  "error_message": null,
  "date": 1784970000000,
  "time_ms": 5,
  "path": "/api/partner/example"
}

O erro comercial geralmente também vem com HTTP 200:

{
  "code": 0,
  "body": null,
  "error_code": 1002,
  "error_message": "Not all params",
  "date": 1784970000000,
  "time_ms": 5,
  "path": "/api/partner/example"
}

Sempre verifique o código HTTP, depois code e depois error_code. Não use o texto error_message como chave de software.

3. Autorização

POST /api/partner/login
Content-Type: application/json
{
  "username": "partner-demo",
  "password": "strong-password"
}

O campo login é suportado como um alias compatível username.

Resposta bem sucedida:

{
  "code": 1,
  "body": {
    "token": "<jwt-token>",
    "user_id": 17,
    "username": "partner-demo"
  },
  "error_code": null,
  "error_message": null
}

Em todas as solicitações protegidas, passe:

Authorization: Bearer <jwt-token>

Erros básicos de login:

CódigoRazão
1002Login ou senha não enviados.
1003Login desconhecido ou senha incorreta.
1004A conta do cliente foi desativada.
1006A data de acesso expirou.
1007O saldo do cliente é zero ou negativo.

Esses erros são retornados de HTTP 200, code = 0. HTTP 401 de um método protegido significa que o JWT está ausente, é inválido, expirou ou foi revogado; Faça login novamente. HTTP 403 significa função inadequada ou acesso negado.

4. Indicador de taxa

Cada resultado selecionado é transmitido como uma linha pronta da linha esportiva:

line_type#game_id#group_id#type_id#rate#coefficient[#player_id]

Exemplos:

line#737779544#1#1#0#1.85
live#738917381|119|5869|0.5#3.6#149439538
  • line_type: line ou live;
  • rate: parâmetro total/handicap ou 0;
  • player_id: ID do jogador opcional;
  • delimitadores # e | são suportados.

Não colete ou corrija o ponteiro manualmente - passe o valor obtido na linha inalterado.

5. Crie um cupom

POST /api/partner/coupons/place
Authorization: Bearer <jwt-token>
Content-Type: application/json
{
  "list_bets": [
    "line#737779544#1#1#0#1.85"
  ],
  "amount": 10,
  "currency": "USD",
  "callback_url": "https://partner.example.com/api/coupon-result",
  "lang": "en",
  "mode": "reject",
  "mode_type": null,
  "multi": false
}
CampoObrigatórioObjetivo
list_betsSimUm ou mais ponteiros.
amountSimO valor positivo de um cupom que está sendo criado.
currencyNãoQualquer designação de string, incluindo moeda virtual.
callback_urlNãoRetorno de chamada de URL; sem callback você não pode enviar, você pode passar null, uma string vazia ou um domínio de site.
langNãoUm código de duas letras para um dos aproximadamente 50 idiomas suportados. A linguagem dos nomes é fixada na criação.
modeNãoreject ou accept; padrão reject.
mode_typePara acceptDireção permitida de mudança de coeficiente.
multiNãoUm cupom geral ou individual; padrão false.

Probabilidades

ConfiguraçõesComportamento
mode = rejectRejeite a criação quando o coeficiente for alterado.
mode = accept, mode_type = 1Aceite apenas promoções.
mode = accept, mode_type = 2Aceite apenas rebaixamento.
mode = accept, mode_type = 3Aceite qualquer alteração.

Comum, expresso e multi

SolicitaçãoResultadoBaixa do saldo do cliente
Um resultadoUm comumamount
Resultados múltiplos, multi = falseUm expressoamount
Resultados múltiplos, multi = trueSepare um único para cada resultadoamount × número de cupons criados

Um trem expresso não pode conter mais de 15 eventos. Você não pode combinar múltiplas apostas na mesma partida, incluindo a partida principal, tempos, períodos, escanteios, faltas e outros subeventos relacionados. Esta combinação retorna 506.

6. Confirmação de cupom e criação de lance

Resposta completa bem-sucedida com cupom e dados de apostas aceitas dentro de events_data:

{
  "code": 1,
  "body": {
    "coupons": [
      {
        "coupon_code": "000000000272",
        "amount": 10,
        "win": 18.5,
        "potential_win": 18.5,
        "real_win": null,
        "coef": 1.85,
        "original_coef": 1.85,
        "calculate_coef": null,
        "has_return": false,
        "date": 1784970000000,
        "status": 0,
        "asian": false,
        "calculate_date": null,
        "coupon_type": 1,
        "events_count": 1,
        "events_data": [
          {
            "id": 912,
            "game_id": 737779544,
            "main_game_id": 737779544,
            "is_sub_game": false,
            "parent_game_id": null,
            "sub_game_key": null,
            "raw_pointer": "line#737779544#1#1#0#1.85",
            "line_type": "line",
            "is_live": false,
            "bet_group_id": 1,
            "bet_group_name": "Match result",
            "bet_id": 1,
            "bet_name": "First team to win",
            "sport_id": 1,
            "sport_name": "Football",
            "tournament_id": 10001,
            "tournament": "National League",
            "event_date": 1784971800000,
            "status": 0,
            "opp1": "Team A",
            "opp2": "Team B",
            "coef": 1.85,
            "calc_coef": null,
            "bet_score": "line#737779544#1#1#0#1.85",
            "calculate_date": null,
            "calculate_score": null,
            "settlement_reason_code": null,
            "settlement_reason": null,
            "placement_score_full": null,
            "placement_score_periods": null,
            "calculation_score_full": null,
            "calculation_score_periods": null,
            "timer": null,
            "dop_name": null,
            "rate": "0",
            "sgame_id": null,
            "game_num": null,
            "stat_id": null,
            "team1_id": 101,
            "team2_id": 102,
            "opp_icon1": 101,
            "opp_icon2": 102
          }
        ]
      }
    ]
  },
  "error_code": null,
  "error_message": null,
  "date": 1784970000015,
  "time_ms": 45,
  "path": "/api/partner/coupons/place"
}

Campos de cupom

Cada item body.coupons[] é um cupom separado criado.

CampoTipoSignificado
coupon_codestringCódigo de cupom público de 12 dígitos. Armazene como uma string para evitar a perda de zeros à esquerda.
amountnumberO valor do cupom transferido na criação.
winnumberValor vencedor exibido atualmente.
potential_winnumberPossíveis ganhos antes da liquidação final.
real_winnumber/nullValor real do pagamento após cálculo; antes do cálculo - null.
coefnumberProporção de cupom atual ou final.
original_coefnumberO coeficiente total do cupom no momento de sua criação.
calculate_coefnumber/nullCoeficiente final calculado; antes do cálculo - null.
has_returnbooleantrue, se o cupom contiver uma aposta com status de reembolso.
dateintegerData de criação do cupom, carimbo de data/hora Unix em milissegundos.
statusintegerStatus atual do cupom. Os valores estão descritos na seção “Status do Cupom e Lance”.
asianbooleanSinal da presença de liquidação asiática, incluindo metade dos ganhos ou perdas.
calculate_dateinteger/nullData de cálculo do cupom em milissegundos; antes do cálculo - null.
coupon_typeintegerTipo de cupom: 1 - comum, 2 - expresso.
events_countintegerNúmero de apostas dentro do cupom.
events_dataarrayA gama completa de apostas incluídas no cupom.

Campos de lance

Cada elemento de events_data[] descreve uma aposta específica aceita dentro do cupom.

CampoTipoSignificado
idinteger/nullID interno da aposta aceita. Usado em conjunto com coupon_code para pesquisar uma taxa dentro de um cupom.
game_idintegerID do evento ou subevento em que a aposta é feita.
main_game_idinteger/nullID da correspondência principal à qual pertence o evento ou subevento.
is_sub_gamebooleantrue, se a aposta for relativa a meio período, set, escanteios ou outro subevento.
parent_game_idinteger/nullO ID do evento pai imediato, se existir.
sub_game_keystring/nullChave técnica de um subevento ou período.
raw_pointerstringO indicador de taxa original aceito pela API.
line_typestringTipo de linha: line - pré-jogo, live - evento em tempo real.
is_livebooleantrue, se a aposta foi criada em uma linha ao vivo.
bet_group_idintegerID do grupo de apostas ou mercado.
bet_group_namestring/nullNome localizado do grupo de apostas.
bet_idintegerID da seleção selecionada dentro do grupo de apostas.
bet_namestring/nullNome completo localizado da seleção selecionada.
sport_idinteger/nullID do esporte.
sport_namestring/nullNome localizado do esporte.
tournament_idinteger/nullID do torneio.
tournamentstring/nullNome localizado do torneio.
event_dateinteger/nullData de início do evento, carimbo de data/hora Unix em milissegundos.
statusintegerStatus atual do cálculo da taxa. Não deve ser confundido com status de cupom.
opp1string/nullNome da primeira equipe ou participante.
opp2string/nullNome da segunda equipe ou participante.
coefnumberAs probabilidades de aposta em que a aposta foi aceita.
calc_coefnumber/nullMultiplicador de aposta calculado; antes do cálculo - null.
bet_scorestringCampo compatível com a API legada contendo o indicador de aposta em vez da pontuação da partida.
calculate_dateinteger/nullData de cálculo da taxa em milissegundos; antes do cálculo - null.
calculate_scorestring/nullA conta usada para calcular a aposta.
settlement_reason_codestring/nullCódigo máquina estável do motivo do pagamento ou devolução; antes do cálculo - null.
settlement_reasonstring/nullTexto explicativo do motivo do pagamento ou devolução; antes do cálculo - null.
placement_score_fullstring/nullPontuação total do evento no momento em que a aposta foi criada, se disponível.
placement_score_periodsstring/nullPontuação por período no momento da criação da aposta, se disponível.
calculation_score_fullstring/nullA pontuação total do evento no momento em que a aposta é liquidada.
calculation_score_periodsstring/nullContabilizar por período no momento do cálculo da taxa.
timerinteger/nullTemporizador de evento no momento do salvamento dos dados, se disponível.
dop_namestring/nullNome do subevento: metade, período, set, inning, etc.
ratestringParâmetro de resultado, por exemplo, o valor do total ou handicap; para um resultado sem parâmetro - "0".
sgame_idstring/nullChave estrangeira do subevento.
game_numinteger/nullNúmero do jogo, se fornecido pela fonte.
stat_idstring/nullID de evento estatístico externo.
team1_idinteger/nullID da primeira equipe ou participante.
team2_idinteger/nullID da segunda equipe ou participante.
opp_icon1integer/nullID compatível do primeiro ícone de comando; corresponde a team1_id.
opp_icon2integer/nullID do ícone da segunda equipe compatível; corresponde a team2_id.

O valor null é normal para dados que ainda não foram calculados ou não estão disponíveis. Não o substitua automaticamente por 0 ou pela sequência vazia.

Considerar o cupom aceito somente se code = 1 e presença de objetos em body.coupons. Antes disso, a cesta é uma escolha preliminar: a seleção pode desaparecer, ser bloqueada ou as probabilidades mudarem.

Depois do sucesso:

  1. salve todos os objetos body.coupons, não apenas o primeiro;
  2. armazene coupon_code como uma string com zeros à esquerda;
  3. salve os dados necessários de events_data;
  4. combinar o cupom com o usuário final;
  5. registrar a transação financeira do usuário no sistema do parceiro.

Identificadores:

CampoObjetivo
coupon_codeCódigo de cupom público.
events_data[].idID da aposta específica aceita dentro do cupom.
retorno de chamada events_data[].uuidO mesmo ID de lance, transmitido como uma string.
batchIdID da versão do pacote de retorno de chamada, não do cupom ou taxa.

currency não é retornado no modelo completo e no retorno de chamada. Se a moeda for necessária, salve o valor da solicitação de criação.

7. Erros de criação

CódigoRazãoAção
10Nenhum corpo de solicitação.Corrija a solicitação.
11Ponteiro inválido.Obtenha o ponteiro atual da linha.
12amount inválido.Passe um número positivo.
501O coeficiente mudou.Mostre o novo valor ou altere mode.
502Não há resultado.Remover/atualizar lance no carrinho.
503O resultado está bloqueado.Informar indisponibilidade temporária.
504Erro de verificação de resultado.Não considere o cupom aceito; repita mais tarde.
506Nas apostas expressas uma partida.Deixe um resultado ou use singles separados.
507Saldo de cliente insuficiente.Recarregue seu saldo ou reduza o valor total.
1002Conjunto de parâmetros inválido.Parâmetros corretos.
10000Erro interno.Registre o erro e verifique o resultado antes de tentar novamente.

Para 501504, a nova API retorna as taxas problemáticas em body.changes[]. Campo change_type: 1 - o coeficiente aumentou, 2 - diminuiu, null - a direção não é aplicável.

Não tente POST /coupons/place cegamente após o tempo limite: a primeira solicitação pode ter sido aceita e tentar novamente criará uma duplicata.

8. Recebendo cupons

OperaçãoPonto finalResultado
Um cupomGET /api/partner/coupons/get?coupon_code={code}Cupom em body.
AtivoGET /api/partner/coupons/activeMatriz em body[].
Cálculos recentesGET /api/partner/coupons/calculated?time=10Matriz em body[]; máximo 120 minutos.
Por código/períodoPOST /api/partner/coupons/resultsMatriz em body.coupons.
Saldo do clienteGET /api/partner/balancebody.balance.

Você pode transferir até 100 valores usando códigos:

{
  "coupon_ids": ["000000000272", "000000000273"]
}

Ou passe o período de criação no máximo 24 horas:

{
  "start_date": 1784880000000,
  "end_date": 1784966400000
}

Não combine coupon_ids e datas na mesma consulta. results filtra por horário de criação e calculated filtra por horário de liquidação final.

9. Status de cupons e apostas

Status do cupom:

CódigoSignificadoFinal
0Ativo ou parcialmente liquidado.Não
2Venceu.Sim
4Perdido.Sim
8Totalmente reembolsado.Sim
15Devolvido para recálculo; espere um novo resultado.Não

Status de lance:

CódigoSignificadocalc_coef
0Não calculado.null
1Ganhar.Coeficiente original
2Perdendo.0
3Retorno.1
4Aguardando recálculo.null
21Metade dos ganhos.(coef + 1) / 2
22Metade da perda.0.5
23Empurre.1

Para provisionamento financeiro para o usuário final, use o real_win pronto. Não use potential_win e não recalcule o pagamento você mesmo. Antes do cálculo, real_win, calculate_coef, calc_coef e calculate_date são iguais a null, não 0.

No primeiro status do cupom 15, caso o resultado anterior já tenha sido processado financeiramente, o parceiro debita novamente amount do usuário final, espera um novo status final e cobra um novo real_win. Proteja as operações contra reprocessamento.

10. Motivo do cálculo

Cada aposta no modelo completo e retorno de chamada possui:

CampoObjetivo
settlement_reason_codeCódigo de motivo de pagamento/reembolso estável.
settlement_reasonTexto fonte explicativo.

Antes do cálculo, ambos os campos são iguais a null. Para uma notificação localizada, use um código como:

  • MATCH_POSTPONED - a partida foi adiada;
  • MATCH_CANCELLED - partida cancelada;
  • MARKET_PUSH – retorno conforme regras de mercado.

Se o código for desconhecido, salve-o e use settlement_reason não vazio como texto substituto. Não calcule o pagamento por motivo - use status e real_win.

Esses campos explicam o cálculo ou retorno que já foi realizado e não são um feed separado em tempo real do status da correspondência.

11. Retorno de chamada

O retorno de chamada é opcional. Um parceiro só pode trabalhar por meio de votação. Para callback o gestor deve habilitar a função e criar callback_secret; A URL é enviada em cada cupom criado.

O parceiro determina o URL de retorno de chamada de forma independente. Na produção deverá usar https://; em um ambiente de teste, http:// é permitido.

O sistema envia:

POST {callback_url}
Content-Type: application/json
X-Coupon-Signature: sha256=<hex_hmac_sha256>

Carga útil curta:

{
  "event": "coupons.settled",
  "batchId": "d407e986f3a64d9d36a77bf532322ef8",
  "couponCount": 1,
  "coupons": [
    {
      "coupon_code": "000000000272",
      "realWin": 18.5,
      "calculate_coefficient": 1.85,
      "status": 2,
      "calculate_date": 1784973600000,
      "events_data": [
        {
          "uuid": "912",
          "status": 1,
          "calculate_coefficient": 1.85,
          "calculate_date": 1784973600000,
          "calculate_score": "2:1",
          "settlement_reason_code": "REMOTE_WIN",
          "settlement_reason": "Win",
          "timer": 0
        }
      ]
    }
  ]
}

Regras obrigatórias:

  1. calcule sha256=<hex(HMAC-SHA256(raw_body, callback_secret))> a partir dos bytes de origem exatos do corpo antes da análise JSON e compare as assinaturas de maneira segura;
  2. processar todos os itens coupons, o pacote pode conter até 100 cupons;
  3. armazene batchId com um índice exclusivo;
  4. batchId repetido não deve repetir a baixa ou acumulação;
  5. um coupon_code pode vir com diferentes batchId durante cálculo progressivo e recálculo;
  6. retorne HTTP 200 somente depois que todo o pacote tiver sido armazenado com segurança.

A resposta mínima bem-sucedida é um HTTP 200 vazio. Avançado:

{
  "success": true,
  "processed": 1
}

processed deve ser igual a couponCount. As respostas 201, 202 e 204 não são consideradas bem-sucedidas.

As repetições são realizadas apenas em caso de timeout, erro de transporte ou HTTP 500, 502, 503, 504: imediatamente, depois de 1, 5, 15 e 60 minutos - não mais que cinco envios. Não há nova tentativa automática em HTTP 200 com success: false ou processed parcial.

12. Votação de reserva

Mesmo com retorno de chamada, verifique periodicamente os resultados:

GET /api/partner/coupons/calculated?time=10

Após um intervalo de mais de 120 minutos, use POST /api/partner/coupons/results em coupon_ids salvo ou em períodos de criação de até 24 horas. Receber novamente a mesma fortuna não deve repetir transações financeiras.

13. Segurança e armazenamento

  • armazenar login, senha, JWT e callback_secret somente no servidor;
  • não passe JWT na URL e não escreva o token completo nos logs;
  • use o tipo decimal para dinheiro;
  • armazene coupon_code como uma string;
  • salve amount, os dados de lance necessários e currency, se usado;
  • distinguir entre status de cupom e lance;
  • aceitar campos desconhecidos e códigos de motivo sem erros;
  • Torne todas as transações financeiras do usuário final idempotentes.

14. API antiga e saque

Rotas antigas continuam sendo suportadas, mas novas integrações devem usar /api/partner/**. Respostas e erros antigos têm formatos diferentes. Para atualizar um cliente existente, use um único arquivo “Migrando da API antiga”.

O saque está em desenvolvimento, não foi totalmente testado e não é recomendado para produção.

15. Lista de verificação final

  • Recebido BASE_URL, login e senha.
  • JWT é transmitido como um token de portador.
  • Os ponteiros são retirados da linha sem modificação.
  • O carrinho é salvo como cupom aceito somente após code = 1.
  • multi processado, restrições expressas e erros 501507.
  • Foi considerada a baixa automática do saldo do cliente.
  • Todos os coupon_code e IDs de lance são salvos.
  • O pagamento final é retirado de real_win.
  • O retorno de chamada é verificado em relação aos bytes de origem e desduplicado usando batchId.
  • A pesquisa de backup foi configurada.
  • O saldo do usuário é separado do saldo do cliente SportAPI.

A documentação detalhada começa com Visão geral da API. O mapa completo do endpoint está no manual.

Precisa de mais documentação ou ajuda com a integração?