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.
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ódigo | Razão |
|---|---|
1002 | Login ou senha não enviados. |
1003 | Login desconhecido ou senha incorreta. |
1004 | A conta do cliente foi desativada. |
1006 | A data de acesso expirou. |
1007 | O 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:lineoulive;rate: parâmetro total/handicap ou0;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
}
| Campo | Obrigatório | Objetivo |
|---|---|---|
list_bets | Sim | Um ou mais ponteiros. |
amount | Sim | O valor positivo de um cupom que está sendo criado. |
currency | Não | Qualquer designação de string, incluindo moeda virtual. |
callback_url | Não | Retorno de chamada de URL; sem callback você não pode enviar, você pode passar null, uma string vazia ou um domínio de site. |
lang | Não | Um código de duas letras para um dos aproximadamente 50 idiomas suportados. A linguagem dos nomes é fixada na criação. |
mode | Não | reject ou accept; padrão reject. |
mode_type | Para accept | Direção permitida de mudança de coeficiente. |
multi | Não | Um cupom geral ou individual; padrão false. |
Probabilidades
| Configurações | Comportamento |
|---|---|
mode = reject | Rejeite a criação quando o coeficiente for alterado. |
mode = accept, mode_type = 1 | Aceite apenas promoções. |
mode = accept, mode_type = 2 | Aceite apenas rebaixamento. |
mode = accept, mode_type = 3 | Aceite qualquer alteração. |
Comum, expresso e multi
| Solicitação | Resultado | Baixa do saldo do cliente |
|---|---|---|
| Um resultado | Um comum | amount |
Resultados múltiplos, multi = false | Um expresso | amount |
Resultados múltiplos, multi = true | Separe um único para cada resultado | amount × 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.
| Campo | Tipo | Significado |
|---|---|---|
coupon_code | string | Código de cupom público de 12 dígitos. Armazene como uma string para evitar a perda de zeros à esquerda. |
amount | number | O valor do cupom transferido na criação. |
win | number | Valor vencedor exibido atualmente. |
potential_win | number | Possíveis ganhos antes da liquidação final. |
real_win | number/null | Valor real do pagamento após cálculo; antes do cálculo - null. |
coef | number | Proporção de cupom atual ou final. |
original_coef | number | O coeficiente total do cupom no momento de sua criação. |
calculate_coef | number/null | Coeficiente final calculado; antes do cálculo - null. |
has_return | boolean | true, se o cupom contiver uma aposta com status de reembolso. |
date | integer | Data de criação do cupom, carimbo de data/hora Unix em milissegundos. |
status | integer | Status atual do cupom. Os valores estão descritos na seção “Status do Cupom e Lance”. |
asian | boolean | Sinal da presença de liquidação asiática, incluindo metade dos ganhos ou perdas. |
calculate_date | integer/null | Data de cálculo do cupom em milissegundos; antes do cálculo - null. |
coupon_type | integer | Tipo de cupom: 1 - comum, 2 - expresso. |
events_count | integer | Número de apostas dentro do cupom. |
events_data | array | A 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.
| Campo | Tipo | Significado |
|---|---|---|
id | integer/null | ID interno da aposta aceita. Usado em conjunto com coupon_code para pesquisar uma taxa dentro de um cupom. |
game_id | integer | ID do evento ou subevento em que a aposta é feita. |
main_game_id | integer/null | ID da correspondência principal à qual pertence o evento ou subevento. |
is_sub_game | boolean | true, se a aposta for relativa a meio período, set, escanteios ou outro subevento. |
parent_game_id | integer/null | O ID do evento pai imediato, se existir. |
sub_game_key | string/null | Chave técnica de um subevento ou período. |
raw_pointer | string | O indicador de taxa original aceito pela API. |
line_type | string | Tipo de linha: line - pré-jogo, live - evento em tempo real. |
is_live | boolean | true, se a aposta foi criada em uma linha ao vivo. |
bet_group_id | integer | ID do grupo de apostas ou mercado. |
bet_group_name | string/null | Nome localizado do grupo de apostas. |
bet_id | integer | ID da seleção selecionada dentro do grupo de apostas. |
bet_name | string/null | Nome completo localizado da seleção selecionada. |
sport_id | integer/null | ID do esporte. |
sport_name | string/null | Nome localizado do esporte. |
tournament_id | integer/null | ID do torneio. |
tournament | string/null | Nome localizado do torneio. |
event_date | integer/null | Data de início do evento, carimbo de data/hora Unix em milissegundos. |
status | integer | Status atual do cálculo da taxa. Não deve ser confundido com status de cupom. |
opp1 | string/null | Nome da primeira equipe ou participante. |
opp2 | string/null | Nome da segunda equipe ou participante. |
coef | number | As probabilidades de aposta em que a aposta foi aceita. |
calc_coef | number/null | Multiplicador de aposta calculado; antes do cálculo - null. |
bet_score | string | Campo compatível com a API legada contendo o indicador de aposta em vez da pontuação da partida. |
calculate_date | integer/null | Data de cálculo da taxa em milissegundos; antes do cálculo - null. |
calculate_score | string/null | A conta usada para calcular a aposta. |
settlement_reason_code | string/null | Código máquina estável do motivo do pagamento ou devolução; antes do cálculo - null. |
settlement_reason | string/null | Texto explicativo do motivo do pagamento ou devolução; antes do cálculo - null. |
placement_score_full | string/null | Pontuação total do evento no momento em que a aposta foi criada, se disponível. |
placement_score_periods | string/null | Pontuação por período no momento da criação da aposta, se disponível. |
calculation_score_full | string/null | A pontuação total do evento no momento em que a aposta é liquidada. |
calculation_score_periods | string/null | Contabilizar por período no momento do cálculo da taxa. |
timer | integer/null | Temporizador de evento no momento do salvamento dos dados, se disponível. |
dop_name | string/null | Nome do subevento: metade, período, set, inning, etc. |
rate | string | Parâmetro de resultado, por exemplo, o valor do total ou handicap; para um resultado sem parâmetro - "0". |
sgame_id | string/null | Chave estrangeira do subevento. |
game_num | integer/null | Número do jogo, se fornecido pela fonte. |
stat_id | string/null | ID de evento estatístico externo. |
team1_id | integer/null | ID da primeira equipe ou participante. |
team2_id | integer/null | ID da segunda equipe ou participante. |
opp_icon1 | integer/null | ID compatível do primeiro ícone de comando; corresponde a team1_id. |
opp_icon2 | integer/null | ID 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:
- salve todos os objetos
body.coupons, não apenas o primeiro; - armazene
coupon_codecomo uma string com zeros à esquerda; - salve os dados necessários de
events_data; - combinar o cupom com o usuário final;
- registrar a transação financeira do usuário no sistema do parceiro.
Identificadores:
| Campo | Objetivo |
|---|---|
coupon_code | Código de cupom público. |
events_data[].id | ID da aposta específica aceita dentro do cupom. |
retorno de chamada events_data[].uuid | O mesmo ID de lance, transmitido como uma string. |
batchId | ID 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ódigo | Razão | Ação |
|---|---|---|
10 | Nenhum corpo de solicitação. | Corrija a solicitação. |
11 | Ponteiro inválido. | Obtenha o ponteiro atual da linha. |
12 | amount inválido. | Passe um número positivo. |
501 | O coeficiente mudou. | Mostre o novo valor ou altere mode. |
502 | Não há resultado. | Remover/atualizar lance no carrinho. |
503 | O resultado está bloqueado. | Informar indisponibilidade temporária. |
504 | Erro de verificação de resultado. | Não considere o cupom aceito; repita mais tarde. |
506 | Nas apostas expressas uma partida. | Deixe um resultado ou use singles separados. |
507 | Saldo de cliente insuficiente. | Recarregue seu saldo ou reduza o valor total. |
1002 | Conjunto de parâmetros inválido. | Parâmetros corretos. |
10000 | Erro interno. | Registre o erro e verifique o resultado antes de tentar novamente. |
Para 501–504, 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ção | Ponto final | Resultado |
|---|---|---|
| Um cupom | GET /api/partner/coupons/get?coupon_code={code} | Cupom em body. |
| Ativo | GET /api/partner/coupons/active | Matriz em body[]. |
| Cálculos recentes | GET /api/partner/coupons/calculated?time=10 | Matriz em body[]; máximo 120 minutos. |
| Por código/período | POST /api/partner/coupons/results | Matriz em body.coupons. |
| Saldo do cliente | GET /api/partner/balance | body.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ódigo | Significado | Final |
|---|---|---|
0 | Ativo ou parcialmente liquidado. | Não |
2 | Venceu. | Sim |
4 | Perdido. | Sim |
8 | Totalmente reembolsado. | Sim |
15 | Devolvido para recálculo; espere um novo resultado. | Não |
Status de lance:
| Código | Significado | calc_coef |
|---|---|---|
0 | Não calculado. | null |
1 | Ganhar. | Coeficiente original |
2 | Perdendo. | 0 |
3 | Retorno. | 1 |
4 | Aguardando recálculo. | null |
21 | Metade dos ganhos. | (coef + 1) / 2 |
22 | Metade da perda. | 0.5 |
23 | Empurre. | 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:
| Campo | Objetivo |
|---|---|
settlement_reason_code | Código de motivo de pagamento/reembolso estável. |
settlement_reason | Texto 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:
- 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; - processar todos os itens
coupons, o pacote pode conter até 100 cupons; - armazene
batchIdcom um índice exclusivo; batchIdrepetido não deve repetir a baixa ou acumulação;- um
coupon_codepode vir com diferentesbatchIddurante cálculo progressivo e recálculo; - retorne HTTP
200somente 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_secretsomente 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_codecomo uma string; - salve
amount, os dados de lance necessários ecurrency, 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. multiprocessado, restrições expressas e erros501–507.- Foi considerada a baixa automática do saldo do cliente.
- Todos os
coupon_codee 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.