{"openapi":"3.1.0","info":{"title":"API pública do BetBackoffice","version":"1.1.0","description":"API pública do BetBackoffice para operadoras que constroem o próprio front-end. Uso **servidor a servidor**: o navegador do jogador nunca chama esta API — o servidor do cliente (BFF) guarda os segredos e assina cada requisição.\n\n## Autenticação (HMAC-SHA256)\n\nToda rota (exceto as públicas de metadados) exige três cabeçalhos:\n\n- `X-Operator-Key`: chave da credencial do operador.\n- `X-Timestamp`: epoch em segundos; tolerância de ±5 minutos.\n- `X-Signature`: hex de `HMAC_SHA256(secret, string_canonica)`.\n\n```text\nstring_canonica = METODO + \"\\n\" + CAMINHO_COM_QUERY + \"\\n\" + TIMESTAMP + \"\\n\" + SHA256_HEX(CORPO)\n```\n\n`CAMINHO_COM_QUERY` é o caminho **exatamente como enviado**, incluindo `/api/v1` e a query string. `CORPO` são os bytes enviados (vazio em GET).\n\n## Idempotência\n\nOperações que criam recursos ou movimentam dinheiro exigem `Idempotency-Key` (8–128 caracteres). Repetir a mesma requisição com a mesma chave devolve a resposta original (`Idempotent-Replayed: true`); a mesma chave com corpo diferente retorna `409 IDEMPOTENCY_CONFLICT`. As chaves são lembradas por 24 horas.\n\n## Webhooks\n\nEventos de saída (seção `webhooks` desta especificação) são enviados por `POST` à URL configurada para o seu operador. Cada entrega traz `X-Webhook-Id` (id do evento, use para deduplicar), `X-Webhook-Timestamp` e `X-Webhook-Signature` = hex de `HMAC_SHA256(webhook_secret, TIMESTAMP + \".\" + CORPO_BRUTO)`. Responda com qualquer `2xx`; outras respostas são retentadas com espera exponencial por até 8 tentativas. Entregas são *at-least-once*: podem repetir. Use `POST /webhooks/test` para validar a integração.\n\n## Convenções\n\n- Valores monetários são **strings decimais** com 2 casas (`\"100.00\"`); a moeda é a do jogador.\n- Datas em ISO 8601 UTC.\n- Erros: `{ \"error\": { \"code\", \"message\", \"requestId\", \"details\" } }`. O `code` é estável; a `message` pode mudar.\n- Todas as respostas trazem `X-Request-Id`.\n- Limite de requisições por operador (padrão 600/min); ao exceder, `429` com `Retry-After`."},"servers":[{"url":"https://backoffice.betfoguete.bet/api/v1","description":"Servidor único: o ambiente é definido pela sua chave — `bk_live_…` opera em produção; `bk_test_…` opera na marca sandbox, com dados isolados."}],"tags":[{"name":"Metadados","description":"Comece por `GET /me`: ele confirma que a assinatura HMAC está correta e mostra a qual operador, marca e ambiente (sandbox ou produção) a sua chave pertence. A especificação e o changelog são públicos."},{"name":"Jogadores","description":"Cadastro e consulta de jogadores da sua marca. Use o `externalId` (o id do jogador no seu sistema) para localizar o jogador sem guardar o id do BetBackoffice. A API não recebe senha: o login é do seu front."},{"name":"Carteira","description":"Saldo e extrato. `available` é o saldo real; `withdrawable` já desconta os saques em aberto."},{"name":"KYC","description":"Verificação de identidade. Você registra o envio do documento; a decisão é da equipe de compliance (em sandbox, use a tag **Sandbox** para simulá-la). Acompanhe pelo webhook `kyc.status_changed`."},{"name":"Depósitos","description":"O meio de pagamento é seu. Crie o depósito (fica `pending`), receba o pagamento no seu PSP e então chame **confirm** para creditar a carteira — ou **fail** se não se concretizar."},{"name":"Saques","description":"Os pedidos entram na fila de análise da equipe. Exige KYC aprovado. O saldo só é debitado no pagamento."},{"name":"Jogos","description":"Catálogo e sessão de jogo. A sessão devolve a `gameUrl` para o navegador do jogador; em sandbox ela é uma sessão de demonstração (saldo fictício)."},{"name":"Webhooks","description":"Eventos de saída assinados (veja a seção *webhooks* desta especificação). Use `POST /webhooks/test` para validar a sua URL e a verificação de assinatura."},{"name":"Sandbox","description":"Atalhos **exclusivos de sandbox** para percorrer o fluxo completo sozinho, simulando as decisões da equipe (KYC e saque). Em produção respondem `403 SANDBOX_ONLY`."}],"x-tagGroups":[{"name":"Comece por aqui","tags":["Metadados"]},{"name":"Conta do jogador","tags":["Jogadores","KYC","Carteira"]},{"name":"Dinheiro","tags":["Depósitos","Saques"]},{"name":"Jogo","tags":["Jogos"]},{"name":"Eventos","tags":["Webhooks"]},{"name":"Sandbox","tags":["Sandbox"]}],"security":[{"OperatorKey":[],"Timestamp":[],"Signature":[]}],"paths":{"/openapi.json":{"get":{"operationId":"getOpenApi","summary":"Especificação OpenAPI","description":"Documento OpenAPI 3.1 desta versão da API. Público, sem autenticação.","tags":["Metadados"],"security":[],"responses":{"200":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"curl \"https://backoffice.betfoguete.bet/api/v1/openapi.json\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"const res = await fetch(\"https://backoffice.betfoguete.bet/api/v1/openapi.json\");\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import requests\n\nres = requests.get(\"https://backoffice.betfoguete.bet/api/v1/openapi.json\")\nprint(res.status_code, res.text)"}]}},"/changelog":{"get":{"operationId":"getChangelog","summary":"Changelog da API","description":"Histórico de mudanças em Markdown. Público, sem autenticação.","tags":["Metadados"],"security":[],"responses":{"200":{"description":"Sucesso","content":{"text/markdown":{"schema":{"type":"string"}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"curl \"https://backoffice.betfoguete.bet/api/v1/changelog\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"const res = await fetch(\"https://backoffice.betfoguete.bet/api/v1/changelog\");\nconsole.log(res.status, await res.text());"},{"lang":"Python","label":"Python (assinado)","source":"import requests\n\nres = requests.get(\"https://backoffice.betfoguete.bet/api/v1/changelog\")\nprint(res.status_code, res.text)"}]}},"/me":{"get":{"operationId":"getMe","summary":"Identidade da credencial","description":"Devolve o operador e a marca associados à credencial usada. Serve para validar a assinatura HMAC na integração.","tags":["Metadados"],"responses":{"200":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"operator":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"environment":{"type":"string","enum":["sandbox","production"]}},"required":["id","name","environment"],"additionalProperties":false},"brand":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"currency":{"type":"string"},"isSandbox":{"description":"Marca de testes: dados isolados da produção","type":"boolean"}},"required":["id","name","currency","isSandbox"],"additionalProperties":false},"apiVersion":{"type":"string"}},"required":["operator","brand","apiVersion"],"additionalProperties":false},"example":{"operator":{"id":"OPR-2c8d51e4-7a03-4b9f-9e16-5d4a1b8c3f70","name":"Cliente Exemplo","environment":"sandbox"},"brand":{"id":"br-sandbox","name":"Sandbox (testes de integração)","currency":"BRL","isSandbox":true},"apiVersion":"1.1.0"}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY=''\nPATH_Q='/api/v1/me'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'GET\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X GET \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/me\";\nconst body = \"\";\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"GET\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"GET\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n  },\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/me\"\nbody = \"\"\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"GET\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n}\nres = requests.request(\"GET\", BASE_URL + path, headers=headers)\nprint(res.status_code, res.json())"}]}},"/postman.json":{"get":{"operationId":"getPostmanCollection","summary":"Coleção Postman","description":"Coleção Postman v2.1 com todas as operações, corpos de exemplo e um script de pré-requisição que assina cada chamada com HMAC. Importe no Postman, defina `operatorKey` e `operatorSecret` (chaves de sandbox) e envie. Público, sem autenticação.","tags":["Metadados"],"security":[],"responses":{"200":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"curl \"https://backoffice.betfoguete.bet/api/v1/postman.json\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"const res = await fetch(\"https://backoffice.betfoguete.bet/api/v1/postman.json\");\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import requests\n\nres = requests.get(\"https://backoffice.betfoguete.bet/api/v1/postman.json\")\nprint(res.status_code, res.text)"}]}},"/signing-snippets.json":{"get":{"operationId":"getSigningSnippets","summary":"Snippets de assinatura","description":"Código para assinar requisições e verificar webhooks em Node.js, Python, PHP, Go, Java, C# e curl/openssl. Público, sem autenticação.","tags":["Metadados"],"security":[],"responses":{"200":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"curl \"https://backoffice.betfoguete.bet/api/v1/signing-snippets.json\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"const res = await fetch(\"https://backoffice.betfoguete.bet/api/v1/signing-snippets.json\");\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import requests\n\nres = requests.get(\"https://backoffice.betfoguete.bet/api/v1/signing-snippets.json\")\nprint(res.status_code, res.text)"}]}},"/test-vectors.json":{"get":{"operationId":"getTestVectors","summary":"Vetores de teste da assinatura","description":"Entradas e assinaturas esperadas (requisição e webhook) para você conferir a sua implementação. Público, sem autenticação.","tags":["Metadados"],"security":[],"responses":{"200":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"curl \"https://backoffice.betfoguete.bet/api/v1/test-vectors.json\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"const res = await fetch(\"https://backoffice.betfoguete.bet/api/v1/test-vectors.json\");\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import requests\n\nres = requests.get(\"https://backoffice.betfoguete.bet/api/v1/test-vectors.json\")\nprint(res.status_code, res.text)"}]}},"/docs":{"get":{"operationId":"getDocsPage","summary":"Página de documentação","description":"Página HTML com a referência interativa, primeiros passos, testador assinado (somente sandbox) e downloads. Pública, sem autenticação.","tags":["Metadados"],"security":[],"responses":{"200":{"description":"Sucesso","content":{"text/html":{"schema":{"type":"string"}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"curl \"https://backoffice.betfoguete.bet/api/v1/docs\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"const res = await fetch(\"https://backoffice.betfoguete.bet/api/v1/docs\");\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import requests\n\nres = requests.get(\"https://backoffice.betfoguete.bet/api/v1/docs\")\nprint(res.status_code, res.text)"}]}},"/players":{"post":{"operationId":"createPlayer","summary":"Cadastrar jogador","description":"Cria a conta do jogador na marca do operador, com KYC `nao_iniciado`. O login do jogador é responsabilidade do seu front-end: a API não recebe senha.","tags":["Jogadores"],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"Chave única por intenção (8–128 caracteres). Reenvie a mesma em retentativas.","example":"6f1e2d3c-4b5a-4978-8a9b-0c1d2e3f4a5b","schema":{"type":"string","minLength":8,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"externalId":{"description":"Identificador do jogador no seu sistema; único por marca","type":"string","minLength":1,"maxLength":128},"name":{"type":"string","minLength":2,"maxLength":200},"email":{"type":"string","maxLength":254,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"cpf":{"description":"CPF válido, com ou sem pontuação","type":"string"},"phone":{"type":"string","pattern":"^\\+?\\d{10,15}$"},"birthDate":{"description":"YYYY-MM-DD; maior de 18 anos","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},"required":["externalId","name","email","cpf","birthDate"]},"example":{"externalId":"jogador-123","name":"Ana Souza","email":"ana.souza@exemplo.com","cpf":"52998224725","phone":"11999998888","birthDate":"1990-05-20"}}}},"responses":{"201":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador do jogador no BetBackoffice","type":"string"},"externalId":{"description":"Identificador do jogador no sistema do operador","anyOf":[{"type":"string"},{"type":"null"}]},"name":{"type":"string"},"email":{"type":"string"},"cpf":{"description":"Somente dígitos","type":"string"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}]},"birthDate":{"description":"YYYY-MM-DD","anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["ativo","suspenso","bloqueado","autoexcluido","encerrado","restrito"]},"kycStatus":{"type":"string","enum":["nao_iniciado","pendente","em_analise","documento_solicitado","aprovado","reprovado","expirado"]},"currency":{"description":"Moeda da conta (ISO 4217)","type":"string"},"createdAt":{"description":"ISO 8601 UTC","type":"string"}},"required":["id","externalId","name","email","cpf","phone","birthDate","status","kycStatus","currency","createdAt"],"additionalProperties":false},"example":{"id":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34","externalId":"jogador-123","name":"Ana Souza","email":"ana.souza@exemplo.com","cpf":"52998224725","phone":"11999998888","birthDate":"1990-05-20","status":"ativo","kycStatus":"nao_iniciado","currency":"BRL","createdAt":"2026-09-25T14:03:11.482Z"}}}},"400":{"description":"Erro: `IDEMPOTENCY_KEY_REQUIRED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"IDEMPOTENCY_KEY_REQUIRED","message":"O cabeçalho Idempotency-Key é obrigatório nesta operação","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"409":{"description":"Erro: `IDEMPOTENCY_CONFLICT`, `IDEMPOTENCY_IN_PROGRESS`, `PLAYER_ALREADY_EXISTS`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"IDEMPOTENCY_CONFLICT","message":"Idempotency-Key já usada com uma requisição diferente","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY='{\"externalId\":\"jogador-123\",\"name\":\"Ana Souza\",\"email\":\"ana.souza@exemplo.com\",\"cpf\":\"52998224725\",\"phone\":\"11999998888\",\"birthDate\":\"1990-05-20\"}'\nPATH_Q='/api/v1/players'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'POST\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X POST \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"$BODY\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/players\";\nconst body = JSON.stringify({\n  \"externalId\": \"jogador-123\",\n  \"name\": \"Ana Souza\",\n  \"email\": \"ana.souza@exemplo.com\",\n  \"cpf\": \"52998224725\",\n  \"phone\": \"11999998888\",\n  \"birthDate\": \"1990-05-20\"\n});\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"POST\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"POST\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n    \"Idempotency-Key\": randomUUID(),\n  },\n  body,\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/players\"\nbody = json.dumps({\n    \"externalId\": \"jogador-123\",\n    \"name\": \"Ana Souza\",\n    \"email\": \"ana.souza@exemplo.com\",\n    \"cpf\": \"52998224725\",\n    \"phone\": \"11999998888\",\n    \"birthDate\": \"1990-05-20\"\n}, separators=(\",\", \":\"))\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"POST\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n    \"Idempotency-Key\": str(uuid.uuid4()),\n}\nres = requests.request(\"POST\", BASE_URL + path, headers=headers, data=body)\nprint(res.status_code, res.json())"}]},"get":{"operationId":"listPlayers","summary":"Buscar jogador por externalId","description":"Devolve o jogador da sua marca com o `externalId` informado (lista vazia se não existir).","tags":["Jogadores"],"parameters":[{"name":"externalId","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":128},"example":"jogador-123"}],"responses":{"200":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"description":"Identificador do jogador no BetBackoffice","type":"string"},"externalId":{"description":"Identificador do jogador no sistema do operador","anyOf":[{"type":"string"},{"type":"null"}]},"name":{"type":"string"},"email":{"type":"string"},"cpf":{"description":"Somente dígitos","type":"string"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}]},"birthDate":{"description":"YYYY-MM-DD","anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["ativo","suspenso","bloqueado","autoexcluido","encerrado","restrito"]},"kycStatus":{"type":"string","enum":["nao_iniciado","pendente","em_analise","documento_solicitado","aprovado","reprovado","expirado"]},"currency":{"description":"Moeda da conta (ISO 4217)","type":"string"},"createdAt":{"description":"ISO 8601 UTC","type":"string"}},"required":["id","externalId","name","email","cpf","phone","birthDate","status","kycStatus","currency","createdAt"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false},"example":{"data":[{"id":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34","externalId":"jogador-123","name":"Ana Souza","email":"ana.souza@exemplo.com","cpf":"52998224725","phone":"11999998888","birthDate":"1990-05-20","status":"ativo","kycStatus":"nao_iniciado","currency":"BRL","createdAt":"2026-09-25T14:03:11.482Z"}]}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY=''\nPATH_Q='/api/v1/players?externalId=jogador-123'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'GET\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X GET \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/players?externalId=jogador-123\";\nconst body = \"\";\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"GET\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"GET\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n  },\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/players?externalId=jogador-123\"\nbody = \"\"\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"GET\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n}\nres = requests.request(\"GET\", BASE_URL + path, headers=headers)\nprint(res.status_code, res.json())"}]}},"/players/{playerId}":{"get":{"operationId":"getPlayer","summary":"Consultar jogador","tags":["Jogadores"],"parameters":[{"name":"playerId","in":"path","required":true,"schema":{"description":"Identificador do jogador no BetBackoffice","type":"string","minLength":1},"description":"Identificador do jogador no BetBackoffice","example":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34"}],"responses":{"200":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador do jogador no BetBackoffice","type":"string"},"externalId":{"description":"Identificador do jogador no sistema do operador","anyOf":[{"type":"string"},{"type":"null"}]},"name":{"type":"string"},"email":{"type":"string"},"cpf":{"description":"Somente dígitos","type":"string"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}]},"birthDate":{"description":"YYYY-MM-DD","anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["ativo","suspenso","bloqueado","autoexcluido","encerrado","restrito"]},"kycStatus":{"type":"string","enum":["nao_iniciado","pendente","em_analise","documento_solicitado","aprovado","reprovado","expirado"]},"currency":{"description":"Moeda da conta (ISO 4217)","type":"string"},"createdAt":{"description":"ISO 8601 UTC","type":"string"}},"required":["id","externalId","name","email","cpf","phone","birthDate","status","kycStatus","currency","createdAt"],"additionalProperties":false},"example":{"id":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34","externalId":"jogador-123","name":"Ana Souza","email":"ana.souza@exemplo.com","cpf":"52998224725","phone":"11999998888","birthDate":"1990-05-20","status":"ativo","kycStatus":"nao_iniciado","currency":"BRL","createdAt":"2026-09-25T14:03:11.482Z"}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"404":{"description":"Erro: `PLAYER_NOT_FOUND`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"PLAYER_NOT_FOUND","message":"Jogador não encontrado","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY=''\nPATH_Q='/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'GET\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X GET \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34\";\nconst body = \"\";\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"GET\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"GET\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n  },\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34\"\nbody = \"\"\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"GET\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n}\nres = requests.request(\"GET\", BASE_URL + path, headers=headers)\nprint(res.status_code, res.json())"}]}},"/players/{playerId}/wallet":{"get":{"operationId":"getWallet","summary":"Saldo do jogador","tags":["Carteira"],"parameters":[{"name":"playerId","in":"path","required":true,"schema":{"description":"Identificador do jogador no BetBackoffice","type":"string","minLength":1},"description":"Identificador do jogador no BetBackoffice","example":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34"}],"responses":{"200":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"playerId":{"type":"string"},"currency":{"type":"string"},"available":{"description":"Saldo real disponível","type":"string","pattern":"^-?\\d+\\.\\d{2}$"},"withdrawable":{"description":"Disponível para saque: saldo real menos saques em aberto","type":"string","pattern":"^-?\\d+\\.\\d{2}$"},"bonus":{"description":"Saldo de bônus","type":"string","pattern":"^-?\\d+\\.\\d{2}$"},"locked":{"description":"Saldo bloqueado","type":"string","pattern":"^-?\\d+\\.\\d{2}$"},"pending":{"description":"Saldo pendente","type":"string","pattern":"^-?\\d+\\.\\d{2}$"}},"required":["playerId","currency","available","withdrawable","bonus","locked","pending"],"additionalProperties":false},"example":{"playerId":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34","currency":"BRL","available":"150.00","withdrawable":"100.00","bonus":"0.00","locked":"0.00","pending":"0.00"}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"404":{"description":"Erro: `PLAYER_NOT_FOUND`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"PLAYER_NOT_FOUND","message":"Jogador não encontrado","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY=''\nPATH_Q='/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/wallet'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'GET\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X GET \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/wallet\";\nconst body = \"\";\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"GET\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"GET\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n  },\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/wallet\"\nbody = \"\"\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"GET\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n}\nres = requests.request(\"GET\", BASE_URL + path, headers=headers)\nprint(res.status_code, res.json())"}]}},"/players/{playerId}/transactions":{"get":{"operationId":"listTransactions","summary":"Extrato do jogador","description":"Lançamentos da carteira, do mais recente ao mais antigo. Paginação por cursor: envie `nextCursor` como `cursor` para a próxima página; `nextCursor` nulo indica o fim.","tags":["Carteira"],"parameters":[{"name":"playerId","in":"path","required":true,"schema":{"description":"Identificador do jogador no BetBackoffice","type":"string","minLength":1},"description":"Identificador do jogador no BetBackoffice","example":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34"},{"name":"limit","in":"query","required":false,"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"example":"20"},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","minLength":1,"maxLength":512}}],"responses":{"200":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"description":"DEPOSIT, WITHDRAWAL, BET, WIN, BONUS_CREDIT, BONUS_DEBIT, REFUND, REVERSAL, ADJUSTMENT...","type":"string"},"wallet":{"type":"string","enum":["REAL","BONUS","LOCKED","PENDING"]},"amount":{"description":"Assinado: positivo credita, negativo debita","type":"string","pattern":"^-?\\d+\\.\\d{2}$"},"balanceAfter":{"description":"Valor decimal em string com 2 casas, ex.: \"100.00\"","type":"string","pattern":"^-?\\d+\\.\\d{2}$"},"currency":{"type":"string"},"reference":{"anyOf":[{"type":"object","properties":{"type":{"type":"string"},"id":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","id"],"additionalProperties":false},{"type":"null"}]},"createdAt":{"description":"ISO 8601 UTC","type":"string"}},"required":["id","type","wallet","amount","balanceAfter","currency","reference","createdAt"],"additionalProperties":false}},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["data","nextCursor"],"additionalProperties":false},"example":{"data":[{"id":"LDG-0b7a4d92-3e15-4c68-9f2a-6d1e8b5c7a30","type":"DEPOSIT","wallet":"REAL","amount":"150.00","balanceAfter":"150.00","currency":"BRL","reference":{"type":"deposit","id":"DEP-7b2e4c10-5a93-4f8e-b1d6-0c9a3e7d2f58"},"createdAt":"2026-09-25T14:09:30.004Z"}],"nextCursor":null}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"404":{"description":"Erro: `PLAYER_NOT_FOUND`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"PLAYER_NOT_FOUND","message":"Jogador não encontrado","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY=''\nPATH_Q='/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/transactions?limit=20'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'GET\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X GET \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/transactions?limit=20\";\nconst body = \"\";\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"GET\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"GET\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n  },\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/transactions?limit=20\"\nbody = \"\"\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"GET\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n}\nres = requests.request(\"GET\", BASE_URL + path, headers=headers)\nprint(res.status_code, res.json())"}]}},"/players/{playerId}/kyc":{"get":{"operationId":"getKyc","summary":"Situação do KYC","description":"Status da verificação de identidade e caso mais recente. A decisão (aprovar/reprovar) é feita pela equipe de compliance no backoffice.","tags":["KYC"],"parameters":[{"name":"playerId","in":"path","required":true,"schema":{"description":"Identificador do jogador no BetBackoffice","type":"string","minLength":1},"description":"Identificador do jogador no BetBackoffice","example":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34"}],"responses":{"200":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"description":"Situação atual da verificação do jogador","type":"string","enum":["nao_iniciado","pendente","em_analise","documento_solicitado","aprovado","reprovado","expirado"]},"case":{"description":"Caso de KYC mais recente, se houver","anyOf":[{"type":"object","properties":{"id":{"type":"string"},"documentType":{"type":"string","enum":["RG","CNH","Passaporte","Comprovante de residência"]},"status":{"type":"string","enum":["nao_iniciado","pendente","em_analise","documento_solicitado","aprovado","reprovado","expirado"]},"submittedAt":{"type":"string"}},"required":["id","documentType","status","submittedAt"],"additionalProperties":false},{"type":"null"}]}},"required":["status","case"],"additionalProperties":false},"example":{"status":"em_analise","case":{"id":"KYC-9e1f5a3c-6b24-4d78-a0c5-3f8b2d7e1a64","documentType":"RG","status":"em_analise","submittedAt":"2026-09-25T14:05:40.120Z"}}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"404":{"description":"Erro: `PLAYER_NOT_FOUND`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"PLAYER_NOT_FOUND","message":"Jogador não encontrado","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY=''\nPATH_Q='/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/kyc'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'GET\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X GET \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/kyc\";\nconst body = \"\";\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"GET\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"GET\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n  },\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/kyc\"\nbody = \"\"\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"GET\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n}\nres = requests.request(\"GET\", BASE_URL + path, headers=headers)\nprint(res.status_code, res.json())"}]}},"/players/{playerId}/kyc/submissions":{"post":{"operationId":"submitKycDocument","summary":"Registrar envio de documento","description":"Registra que o jogador enviou um documento e coloca o KYC `em_analise`. Nesta versão a API **não recebe o arquivo**: guarde-o no seu sistema e informe uma `reference` opaca para a equipe de compliance localizá-lo.","tags":["KYC"],"parameters":[{"name":"playerId","in":"path","required":true,"schema":{"description":"Identificador do jogador no BetBackoffice","type":"string","minLength":1},"description":"Identificador do jogador no BetBackoffice","example":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34"},{"name":"Idempotency-Key","in":"header","required":true,"description":"Chave única por intenção (8–128 caracteres). Reenvie a mesma em retentativas.","example":"6f1e2d3c-4b5a-4978-8a9b-0c1d2e3f4a5b","schema":{"type":"string","minLength":8,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"documentType":{"type":"string","enum":["RG","CNH","Passaporte","Comprovante de residência"]},"reference":{"description":"Referência do documento no seu sistema","type":"string","minLength":1,"maxLength":128}},"required":["documentType"]},"example":{"documentType":"RG","reference":"doc-ana-souza-001"}}}},"responses":{"201":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"description":"Situação atual da verificação do jogador","type":"string","enum":["nao_iniciado","pendente","em_analise","documento_solicitado","aprovado","reprovado","expirado"]},"case":{"description":"Caso de KYC mais recente, se houver","anyOf":[{"type":"object","properties":{"id":{"type":"string"},"documentType":{"type":"string","enum":["RG","CNH","Passaporte","Comprovante de residência"]},"status":{"type":"string","enum":["nao_iniciado","pendente","em_analise","documento_solicitado","aprovado","reprovado","expirado"]},"submittedAt":{"type":"string"}},"required":["id","documentType","status","submittedAt"],"additionalProperties":false},{"type":"null"}]}},"required":["status","case"],"additionalProperties":false},"example":{"status":"em_analise","case":{"id":"KYC-9e1f5a3c-6b24-4d78-a0c5-3f8b2d7e1a64","documentType":"RG","status":"em_analise","submittedAt":"2026-09-25T14:05:40.120Z"}}}}},"400":{"description":"Erro: `IDEMPOTENCY_KEY_REQUIRED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"IDEMPOTENCY_KEY_REQUIRED","message":"O cabeçalho Idempotency-Key é obrigatório nesta operação","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"404":{"description":"Erro: `PLAYER_NOT_FOUND`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"PLAYER_NOT_FOUND","message":"Jogador não encontrado","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"409":{"description":"Erro: `IDEMPOTENCY_CONFLICT`, `IDEMPOTENCY_IN_PROGRESS`, `KYC_ALREADY_APPROVED`, `PLAYER_NOT_ACTIVE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"IDEMPOTENCY_CONFLICT","message":"Idempotency-Key já usada com uma requisição diferente","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY='{\"documentType\":\"RG\",\"reference\":\"doc-ana-souza-001\"}'\nPATH_Q='/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/kyc/submissions'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'POST\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X POST \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"$BODY\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/kyc/submissions\";\nconst body = JSON.stringify({\n  \"documentType\": \"RG\",\n  \"reference\": \"doc-ana-souza-001\"\n});\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"POST\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"POST\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n    \"Idempotency-Key\": randomUUID(),\n  },\n  body,\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/kyc/submissions\"\nbody = json.dumps({\n    \"documentType\": \"RG\",\n    \"reference\": \"doc-ana-souza-001\"\n}, separators=(\",\", \":\"))\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"POST\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n    \"Idempotency-Key\": str(uuid.uuid4()),\n}\nres = requests.request(\"POST\", BASE_URL + path, headers=headers, data=body)\nprint(res.status_code, res.json())"}]}},"/players/{playerId}/deposits":{"post":{"operationId":"createDeposit","summary":"Criar depósito","description":"Registra a intenção de depósito como `pending`. O meio de pagamento é seu: depois de receber o pagamento, chame `POST /deposits/{depositId}/confirm` para creditar a carteira (ou `/fail` se não se concretizar). Respeita autoexclusão e o limite diário de depósito do jogador.","tags":["Depósitos"],"parameters":[{"name":"playerId","in":"path","required":true,"schema":{"description":"Identificador do jogador no BetBackoffice","type":"string","minLength":1},"description":"Identificador do jogador no BetBackoffice","example":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34"},{"name":"Idempotency-Key","in":"header","required":true,"description":"Chave única por intenção (8–128 caracteres). Reenvie a mesma em retentativas.","example":"6f1e2d3c-4b5a-4978-8a9b-0c1d2e3f4a5b","schema":{"type":"string","minLength":8,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"amount":{"description":"Valor decimal positivo em string com até 2 casas, ex.: \"100.00\"","type":"string"},"currency":{"description":"Deve ser a moeda do jogador","type":"string","minLength":3,"maxLength":3},"method":{"type":"string","enum":["PIX","TED","Cartão","Carteira digital"]},"externalReference":{"description":"Identificador do pagamento no seu PSP; único por operador","type":"string","minLength":1,"maxLength":128}},"required":["amount","currency","method"]},"example":{"amount":"150.00","currency":"BRL","method":"PIX","externalReference":"psp-2026-000123"}}}},"responses":{"201":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"playerId":{"type":"string"},"amount":{"description":"Valor decimal em string com 2 casas, ex.: \"100.00\"","type":"string","pattern":"^-?\\d+\\.\\d{2}$"},"currency":{"type":"string"},"method":{"type":"string","enum":["PIX","TED","Cartão","Carteira digital"]},"status":{"type":"string","enum":["pending","confirmed","failed","expired"]},"externalReference":{"anyOf":[{"type":"string"},{"type":"null"}]},"failureReason":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string"},"confirmedAt":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","playerId","amount","currency","method","status","externalReference","failureReason","createdAt","confirmedAt"],"additionalProperties":false},"example":{"id":"DEP-7b2e4c10-5a93-4f8e-b1d6-0c9a3e7d2f58","playerId":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34","amount":"150.00","currency":"BRL","method":"PIX","status":"pending","externalReference":"psp-2026-000123","failureReason":null,"createdAt":"2026-09-25T14:08:02.771Z","confirmedAt":null}}}},"400":{"description":"Erro: `IDEMPOTENCY_KEY_REQUIRED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"IDEMPOTENCY_KEY_REQUIRED","message":"O cabeçalho Idempotency-Key é obrigatório nesta operação","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"404":{"description":"Erro: `PLAYER_NOT_FOUND`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"PLAYER_NOT_FOUND","message":"Jogador não encontrado","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"409":{"description":"Erro: `IDEMPOTENCY_CONFLICT`, `IDEMPOTENCY_IN_PROGRESS`, `PLAYER_NOT_ACTIVE`, `RG_BLOCKED`, `DEPOSIT_ALREADY_EXISTS`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"IDEMPOTENCY_CONFLICT","message":"Idempotency-Key já usada com uma requisição diferente","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`, `CURRENCY_MISMATCH`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY='{\"amount\":\"150.00\",\"currency\":\"BRL\",\"method\":\"PIX\",\"externalReference\":\"psp-2026-000123\"}'\nPATH_Q='/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/deposits'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'POST\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X POST \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"$BODY\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/deposits\";\nconst body = JSON.stringify({\n  \"amount\": \"150.00\",\n  \"currency\": \"BRL\",\n  \"method\": \"PIX\",\n  \"externalReference\": \"psp-2026-000123\"\n});\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"POST\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"POST\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n    \"Idempotency-Key\": randomUUID(),\n  },\n  body,\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/deposits\"\nbody = json.dumps({\n    \"amount\": \"150.00\",\n    \"currency\": \"BRL\",\n    \"method\": \"PIX\",\n    \"externalReference\": \"psp-2026-000123\"\n}, separators=(\",\", \":\"))\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"POST\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n    \"Idempotency-Key\": str(uuid.uuid4()),\n}\nres = requests.request(\"POST\", BASE_URL + path, headers=headers, data=body)\nprint(res.status_code, res.json())"}]}},"/deposits/{depositId}":{"get":{"operationId":"getDeposit","summary":"Consultar depósito","tags":["Depósitos"],"parameters":[{"name":"depositId","in":"path","required":true,"schema":{"type":"string","minLength":1},"example":"DEP-7b2e4c10-5a93-4f8e-b1d6-0c9a3e7d2f58"}],"responses":{"200":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"playerId":{"type":"string"},"amount":{"description":"Valor decimal em string com 2 casas, ex.: \"100.00\"","type":"string","pattern":"^-?\\d+\\.\\d{2}$"},"currency":{"type":"string"},"method":{"type":"string","enum":["PIX","TED","Cartão","Carteira digital"]},"status":{"type":"string","enum":["pending","confirmed","failed","expired"]},"externalReference":{"anyOf":[{"type":"string"},{"type":"null"}]},"failureReason":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string"},"confirmedAt":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","playerId","amount","currency","method","status","externalReference","failureReason","createdAt","confirmedAt"],"additionalProperties":false},"example":{"id":"DEP-7b2e4c10-5a93-4f8e-b1d6-0c9a3e7d2f58","playerId":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34","amount":"150.00","currency":"BRL","method":"PIX","status":"pending","externalReference":"psp-2026-000123","failureReason":null,"createdAt":"2026-09-25T14:08:02.771Z","confirmedAt":null}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"404":{"description":"Erro: `DEPOSIT_NOT_FOUND`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"DEPOSIT_NOT_FOUND","message":"Depósito não encontrado","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY=''\nPATH_Q='/api/v1/deposits/DEP-7b2e4c10-5a93-4f8e-b1d6-0c9a3e7d2f58'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'GET\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X GET \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/deposits/DEP-7b2e4c10-5a93-4f8e-b1d6-0c9a3e7d2f58\";\nconst body = \"\";\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"GET\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"GET\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n  },\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/deposits/DEP-7b2e4c10-5a93-4f8e-b1d6-0c9a3e7d2f58\"\nbody = \"\"\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"GET\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n}\nres = requests.request(\"GET\", BASE_URL + path, headers=headers)\nprint(res.status_code, res.json())"}]}},"/deposits/{depositId}/confirm":{"post":{"operationId":"confirmDeposit","summary":"Confirmar depósito","description":"Confirma que o pagamento foi recebido e credita o valor na carteira real do jogador, uma única vez.","tags":["Depósitos"],"parameters":[{"name":"depositId","in":"path","required":true,"schema":{"type":"string","minLength":1},"example":"DEP-7b2e4c10-5a93-4f8e-b1d6-0c9a3e7d2f58"},{"name":"Idempotency-Key","in":"header","required":true,"description":"Chave única por intenção (8–128 caracteres). Reenvie a mesma em retentativas.","example":"6f1e2d3c-4b5a-4978-8a9b-0c1d2e3f4a5b","schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"playerId":{"type":"string"},"amount":{"description":"Valor decimal em string com 2 casas, ex.: \"100.00\"","type":"string","pattern":"^-?\\d+\\.\\d{2}$"},"currency":{"type":"string"},"method":{"type":"string","enum":["PIX","TED","Cartão","Carteira digital"]},"status":{"type":"string","enum":["pending","confirmed","failed","expired"]},"externalReference":{"anyOf":[{"type":"string"},{"type":"null"}]},"failureReason":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string"},"confirmedAt":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","playerId","amount","currency","method","status","externalReference","failureReason","createdAt","confirmedAt"],"additionalProperties":false},"example":{"id":"DEP-7b2e4c10-5a93-4f8e-b1d6-0c9a3e7d2f58","playerId":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34","amount":"150.00","currency":"BRL","method":"PIX","status":"confirmed","externalReference":"psp-2026-000123","failureReason":null,"createdAt":"2026-09-25T14:08:02.771Z","confirmedAt":"2026-09-25T14:09:30.004Z"}}}},"400":{"description":"Erro: `IDEMPOTENCY_KEY_REQUIRED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"IDEMPOTENCY_KEY_REQUIRED","message":"O cabeçalho Idempotency-Key é obrigatório nesta operação","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"404":{"description":"Erro: `DEPOSIT_NOT_FOUND`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"DEPOSIT_NOT_FOUND","message":"Depósito não encontrado","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"409":{"description":"Erro: `IDEMPOTENCY_CONFLICT`, `IDEMPOTENCY_IN_PROGRESS`, `DEPOSIT_NOT_PENDING`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"IDEMPOTENCY_CONFLICT","message":"Idempotency-Key já usada com uma requisição diferente","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY=''\nPATH_Q='/api/v1/deposits/DEP-7b2e4c10-5a93-4f8e-b1d6-0c9a3e7d2f58/confirm'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'POST\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X POST \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\" \\\n  -H \"Idempotency-Key: $(uuidgen)\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/deposits/DEP-7b2e4c10-5a93-4f8e-b1d6-0c9a3e7d2f58/confirm\";\nconst body = \"\";\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"POST\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"POST\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n    \"Idempotency-Key\": randomUUID(),\n  },\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/deposits/DEP-7b2e4c10-5a93-4f8e-b1d6-0c9a3e7d2f58/confirm\"\nbody = \"\"\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"POST\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n    \"Idempotency-Key\": str(uuid.uuid4()),\n}\nres = requests.request(\"POST\", BASE_URL + path, headers=headers)\nprint(res.status_code, res.json())"}]}},"/deposits/{depositId}/fail":{"post":{"operationId":"failDeposit","summary":"Marcar depósito como não concretizado","tags":["Depósitos"],"parameters":[{"name":"depositId","in":"path","required":true,"schema":{"type":"string","minLength":1},"example":"DEP-7b2e4c10-5a93-4f8e-b1d6-0c9a3e7d2f58"},{"name":"Idempotency-Key","in":"header","required":true,"description":"Chave única por intenção (8–128 caracteres). Reenvie a mesma em retentativas.","example":"6f1e2d3c-4b5a-4978-8a9b-0c1d2e3f4a5b","schema":{"type":"string","minLength":8,"maxLength":128}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":200}}},"example":{"reason":"pagamento expirou no PSP"}}}},"responses":{"200":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"playerId":{"type":"string"},"amount":{"description":"Valor decimal em string com 2 casas, ex.: \"100.00\"","type":"string","pattern":"^-?\\d+\\.\\d{2}$"},"currency":{"type":"string"},"method":{"type":"string","enum":["PIX","TED","Cartão","Carteira digital"]},"status":{"type":"string","enum":["pending","confirmed","failed","expired"]},"externalReference":{"anyOf":[{"type":"string"},{"type":"null"}]},"failureReason":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string"},"confirmedAt":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","playerId","amount","currency","method","status","externalReference","failureReason","createdAt","confirmedAt"],"additionalProperties":false},"example":{"id":"DEP-7b2e4c10-5a93-4f8e-b1d6-0c9a3e7d2f58","playerId":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34","amount":"150.00","currency":"BRL","method":"PIX","status":"failed","externalReference":"psp-2026-000123","failureReason":"pagamento expirou no PSP","createdAt":"2026-09-25T14:08:02.771Z","confirmedAt":null}}}},"400":{"description":"Erro: `IDEMPOTENCY_KEY_REQUIRED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"IDEMPOTENCY_KEY_REQUIRED","message":"O cabeçalho Idempotency-Key é obrigatório nesta operação","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"404":{"description":"Erro: `DEPOSIT_NOT_FOUND`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"DEPOSIT_NOT_FOUND","message":"Depósito não encontrado","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"409":{"description":"Erro: `IDEMPOTENCY_CONFLICT`, `IDEMPOTENCY_IN_PROGRESS`, `DEPOSIT_NOT_PENDING`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"IDEMPOTENCY_CONFLICT","message":"Idempotency-Key já usada com uma requisição diferente","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY='{\"reason\":\"pagamento expirou no PSP\"}'\nPATH_Q='/api/v1/deposits/DEP-7b2e4c10-5a93-4f8e-b1d6-0c9a3e7d2f58/fail'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'POST\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X POST \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"$BODY\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/deposits/DEP-7b2e4c10-5a93-4f8e-b1d6-0c9a3e7d2f58/fail\";\nconst body = JSON.stringify({\n  \"reason\": \"pagamento expirou no PSP\"\n});\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"POST\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"POST\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n    \"Idempotency-Key\": randomUUID(),\n  },\n  body,\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/deposits/DEP-7b2e4c10-5a93-4f8e-b1d6-0c9a3e7d2f58/fail\"\nbody = json.dumps({\n    \"reason\": \"pagamento expirou no PSP\"\n}, separators=(\",\", \":\"))\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"POST\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n    \"Idempotency-Key\": str(uuid.uuid4()),\n}\nres = requests.request(\"POST\", BASE_URL + path, headers=headers, data=body)\nprint(res.status_code, res.json())"}]}},"/players/{playerId}/withdrawals":{"post":{"operationId":"requestWithdrawal","summary":"Solicitar saque","description":"Cria um pedido de saque na fila de análise do backoffice (aprovação e alçadas são da equipe). Exige KYC aprovado e jogador ativo, sem rollover de bônus pendente, e saldo real disponível descontados os saques ainda em aberto. O saldo é debitado no pagamento.","tags":["Saques"],"parameters":[{"name":"playerId","in":"path","required":true,"schema":{"description":"Identificador do jogador no BetBackoffice","type":"string","minLength":1},"description":"Identificador do jogador no BetBackoffice","example":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34"},{"name":"Idempotency-Key","in":"header","required":true,"description":"Chave única por intenção (8–128 caracteres). Reenvie a mesma em retentativas.","example":"6f1e2d3c-4b5a-4978-8a9b-0c1d2e3f4a5b","schema":{"type":"string","minLength":8,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"amount":{"description":"Valor decimal positivo em string com até 2 casas, ex.: \"100.00\"","type":"string"},"currency":{"description":"Deve ser a moeda do jogador","type":"string","minLength":3,"maxLength":3},"method":{"type":"string","enum":["PIX","TED","Cartão","Carteira digital"]},"destination":{"description":"Destino do pagamento, ex.: chave PIX","type":"string","minLength":1,"maxLength":140}},"required":["amount","currency","method","destination"]},"example":{"amount":"50.00","currency":"BRL","method":"PIX","destination":"ana.souza@exemplo.com"}}}},"responses":{"201":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"playerId":{"type":"string"},"amount":{"description":"Valor decimal em string com 2 casas, ex.: \"100.00\"","type":"string","pattern":"^-?\\d+\\.\\d{2}$"},"currency":{"type":"string"},"method":{"type":"string","enum":["PIX","TED","Cartão","Carteira digital"]},"destination":{"type":"string"},"status":{"description":"under_review: em análise pela equipe; approved: aprovado, aguardando pagamento; paid: pago; rejected: recusado; cancelled: cancelado; failed: falhou","type":"string","enum":["under_review","approved","paid","rejected","cancelled","failed"]},"requestedAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","playerId","amount","currency","method","destination","status","requestedAt","updatedAt"],"additionalProperties":false},"example":{"id":"WD-c41d9e07-2b6a-4d35-8f10-7e5b9a3c6d82","playerId":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34","amount":"50.00","currency":"BRL","method":"PIX","destination":"ana.souza@exemplo.com","status":"under_review","requestedAt":"2026-09-25T14:20:15.300Z","updatedAt":"2026-09-25T14:20:15.300Z"}}}},"400":{"description":"Erro: `IDEMPOTENCY_KEY_REQUIRED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"IDEMPOTENCY_KEY_REQUIRED","message":"O cabeçalho Idempotency-Key é obrigatório nesta operação","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"402":{"description":"Erro: `INSUFFICIENT_BALANCE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_BALANCE","message":"Saldo insuficiente","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`, `KYC_REQUIRED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"404":{"description":"Erro: `PLAYER_NOT_FOUND`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"PLAYER_NOT_FOUND","message":"Jogador não encontrado","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"409":{"description":"Erro: `IDEMPOTENCY_CONFLICT`, `IDEMPOTENCY_IN_PROGRESS`, `PLAYER_NOT_ACTIVE`, `RG_BLOCKED`, `BONUS_ROLLOVER_PENDING`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"IDEMPOTENCY_CONFLICT","message":"Idempotency-Key já usada com uma requisição diferente","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`, `CURRENCY_MISMATCH`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY='{\"amount\":\"50.00\",\"currency\":\"BRL\",\"method\":\"PIX\",\"destination\":\"ana.souza@exemplo.com\"}'\nPATH_Q='/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/withdrawals'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'POST\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X POST \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"$BODY\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/withdrawals\";\nconst body = JSON.stringify({\n  \"amount\": \"50.00\",\n  \"currency\": \"BRL\",\n  \"method\": \"PIX\",\n  \"destination\": \"ana.souza@exemplo.com\"\n});\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"POST\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"POST\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n    \"Idempotency-Key\": randomUUID(),\n  },\n  body,\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/withdrawals\"\nbody = json.dumps({\n    \"amount\": \"50.00\",\n    \"currency\": \"BRL\",\n    \"method\": \"PIX\",\n    \"destination\": \"ana.souza@exemplo.com\"\n}, separators=(\",\", \":\"))\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"POST\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n    \"Idempotency-Key\": str(uuid.uuid4()),\n}\nres = requests.request(\"POST\", BASE_URL + path, headers=headers, data=body)\nprint(res.status_code, res.json())"}]}},"/withdrawals/{withdrawalId}":{"get":{"operationId":"getWithdrawal","summary":"Consultar saque","tags":["Saques"],"parameters":[{"name":"withdrawalId","in":"path","required":true,"schema":{"type":"string","minLength":1},"example":"WD-c41d9e07-2b6a-4d35-8f10-7e5b9a3c6d82"}],"responses":{"200":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"playerId":{"type":"string"},"amount":{"description":"Valor decimal em string com 2 casas, ex.: \"100.00\"","type":"string","pattern":"^-?\\d+\\.\\d{2}$"},"currency":{"type":"string"},"method":{"type":"string","enum":["PIX","TED","Cartão","Carteira digital"]},"destination":{"type":"string"},"status":{"description":"under_review: em análise pela equipe; approved: aprovado, aguardando pagamento; paid: pago; rejected: recusado; cancelled: cancelado; failed: falhou","type":"string","enum":["under_review","approved","paid","rejected","cancelled","failed"]},"requestedAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","playerId","amount","currency","method","destination","status","requestedAt","updatedAt"],"additionalProperties":false},"example":{"id":"WD-c41d9e07-2b6a-4d35-8f10-7e5b9a3c6d82","playerId":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34","amount":"50.00","currency":"BRL","method":"PIX","destination":"ana.souza@exemplo.com","status":"under_review","requestedAt":"2026-09-25T14:20:15.300Z","updatedAt":"2026-09-25T14:20:15.300Z"}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"404":{"description":"Erro: `WITHDRAWAL_NOT_FOUND`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"WITHDRAWAL_NOT_FOUND","message":"Saque não encontrado","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY=''\nPATH_Q='/api/v1/withdrawals/WD-c41d9e07-2b6a-4d35-8f10-7e5b9a3c6d82'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'GET\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X GET \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/withdrawals/WD-c41d9e07-2b6a-4d35-8f10-7e5b9a3c6d82\";\nconst body = \"\";\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"GET\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"GET\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n  },\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/withdrawals/WD-c41d9e07-2b6a-4d35-8f10-7e5b9a3c6d82\"\nbody = \"\"\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"GET\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n}\nres = requests.request(\"GET\", BASE_URL + path, headers=headers)\nprint(res.status_code, res.json())"}]}},"/withdrawals/{withdrawalId}/cancel":{"post":{"operationId":"cancelWithdrawal","summary":"Cancelar saque","description":"Só é possível enquanto o saque ainda não foi aprovado pela equipe.","tags":["Saques"],"parameters":[{"name":"withdrawalId","in":"path","required":true,"schema":{"type":"string","minLength":1},"example":"WD-c41d9e07-2b6a-4d35-8f10-7e5b9a3c6d82"},{"name":"Idempotency-Key","in":"header","required":true,"description":"Chave única por intenção (8–128 caracteres). Reenvie a mesma em retentativas.","example":"6f1e2d3c-4b5a-4978-8a9b-0c1d2e3f4a5b","schema":{"type":"string","minLength":8,"maxLength":128}}],"responses":{"200":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"playerId":{"type":"string"},"amount":{"description":"Valor decimal em string com 2 casas, ex.: \"100.00\"","type":"string","pattern":"^-?\\d+\\.\\d{2}$"},"currency":{"type":"string"},"method":{"type":"string","enum":["PIX","TED","Cartão","Carteira digital"]},"destination":{"type":"string"},"status":{"description":"under_review: em análise pela equipe; approved: aprovado, aguardando pagamento; paid: pago; rejected: recusado; cancelled: cancelado; failed: falhou","type":"string","enum":["under_review","approved","paid","rejected","cancelled","failed"]},"requestedAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","playerId","amount","currency","method","destination","status","requestedAt","updatedAt"],"additionalProperties":false},"example":{"id":"WD-c41d9e07-2b6a-4d35-8f10-7e5b9a3c6d82","playerId":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34","amount":"50.00","currency":"BRL","method":"PIX","destination":"ana.souza@exemplo.com","status":"cancelled","requestedAt":"2026-09-25T14:20:15.300Z","updatedAt":"2026-09-25T14:20:15.300Z"}}}},"400":{"description":"Erro: `IDEMPOTENCY_KEY_REQUIRED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"IDEMPOTENCY_KEY_REQUIRED","message":"O cabeçalho Idempotency-Key é obrigatório nesta operação","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"404":{"description":"Erro: `WITHDRAWAL_NOT_FOUND`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"WITHDRAWAL_NOT_FOUND","message":"Saque não encontrado","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"409":{"description":"Erro: `IDEMPOTENCY_CONFLICT`, `IDEMPOTENCY_IN_PROGRESS`, `WITHDRAWAL_NOT_CANCELLABLE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"IDEMPOTENCY_CONFLICT","message":"Idempotency-Key já usada com uma requisição diferente","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY=''\nPATH_Q='/api/v1/withdrawals/WD-c41d9e07-2b6a-4d35-8f10-7e5b9a3c6d82/cancel'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'POST\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X POST \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\" \\\n  -H \"Idempotency-Key: $(uuidgen)\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/withdrawals/WD-c41d9e07-2b6a-4d35-8f10-7e5b9a3c6d82/cancel\";\nconst body = \"\";\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"POST\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"POST\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n    \"Idempotency-Key\": randomUUID(),\n  },\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/withdrawals/WD-c41d9e07-2b6a-4d35-8f10-7e5b9a3c6d82/cancel\"\nbody = \"\"\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"POST\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n    \"Idempotency-Key\": str(uuid.uuid4()),\n}\nres = requests.request(\"POST\", BASE_URL + path, headers=headers)\nprint(res.status_code, res.json())"}]}},"/games":{"get":{"operationId":"listGames","summary":"Catálogo de jogos","tags":["Jogos"],"responses":{"200":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"description":"Use como gameId ao criar a sessão","type":"string"},"name":{"type":"string"},"category":{"type":"string"},"active":{"type":"boolean"}},"required":["id","name","category","active"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false},"example":{"data":[{"id":"rocket-crash","name":"Rocket Crash","category":"crash","active":true},{"id":"mines","name":"Mines","category":"mines","active":true}]}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"502":{"description":"Erro: `PROVIDER_UNAVAILABLE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"PROVIDER_UNAVAILABLE","message":"Game Provider indisponível","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY=''\nPATH_Q='/api/v1/games'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'GET\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X GET \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/games\";\nconst body = \"\";\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"GET\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"GET\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n  },\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/games\"\nbody = \"\"\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"GET\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n}\nres = requests.request(\"GET\", BASE_URL + path, headers=headers)\nprint(res.status_code, res.json())"}]}},"/players/{playerId}/game-sessions":{"post":{"operationId":"createGameSession","summary":"Criar sessão de jogo","description":"Cria uma sessão de jogo com dinheiro real e devolve a `gameUrl`, que o seu front abre (ex.: em um iframe). Exige jogador ativo e KYC aprovado. A URL carrega um token de curta duração (30 minutos): **não a registre em logs nem a repasse a terceiros**. Cada chamada cria uma nova sessão (não usa `Idempotency-Key`).","tags":["Jogos"],"parameters":[{"name":"playerId","in":"path","required":true,"schema":{"description":"Identificador do jogador no BetBackoffice","type":"string","minLength":1},"description":"Identificador do jogador no BetBackoffice","example":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"gameId":{"type":"string","minLength":1,"maxLength":64},"locale":{"default":"pt-BR","type":"string","pattern":"^[a-z]{2}(-[A-Z]{2})?$"},"device":{"default":"desktop","type":"string","enum":["desktop","tablet","mobile"]}},"required":["gameId"]},"example":{"gameId":"rocket-crash","locale":"pt-BR","device":"desktop"}}}},"responses":{"201":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"sessionId":{"type":"string"},"gameUrl":{"description":"URL para abrir o jogo; contém token de curta duração","type":"string"},"expiresAt":{"description":"ISO 8601 UTC","type":"string"}},"required":["sessionId","gameUrl","expiresAt"],"additionalProperties":false},"example":{"sessionId":"b3a1f6c2-49d0-4e7b-8a15-2c6d9e0f4b71","gameUrl":"https://games.exemplo.com/play/rocket-crash?token=…","expiresAt":"2026-09-25T14:45:00.000Z"}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`, `KYC_REQUIRED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"404":{"description":"Erro: `PLAYER_NOT_FOUND`, `GAME_NOT_FOUND`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"PLAYER_NOT_FOUND","message":"Jogador não encontrado","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"409":{"description":"Erro: `PLAYER_NOT_ACTIVE`, `RG_BLOCKED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"PLAYER_NOT_ACTIVE","message":"Jogador não está ativo","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"502":{"description":"Erro: `PROVIDER_UNAVAILABLE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"PROVIDER_UNAVAILABLE","message":"Game Provider indisponível","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY='{\"gameId\":\"rocket-crash\",\"locale\":\"pt-BR\",\"device\":\"desktop\"}'\nPATH_Q='/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/game-sessions'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'POST\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X POST \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"$BODY\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/game-sessions\";\nconst body = JSON.stringify({\n  \"gameId\": \"rocket-crash\",\n  \"locale\": \"pt-BR\",\n  \"device\": \"desktop\"\n});\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"POST\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"POST\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n  },\n  body,\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/game-sessions\"\nbody = json.dumps({\n    \"gameId\": \"rocket-crash\",\n    \"locale\": \"pt-BR\",\n    \"device\": \"desktop\"\n}, separators=(\",\", \":\"))\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"POST\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n}\nres = requests.request(\"POST\", BASE_URL + path, headers=headers, data=body)\nprint(res.status_code, res.json())"}]}},"/webhooks/test":{"post":{"operationId":"sendTestWebhook","summary":"Enviar webhook de teste","description":"Enfileira um evento `webhook.test` para a URL de webhook configurada para o seu operador, para validar a URL e a verificação de assinatura. A entrega é assíncrona (poucos segundos). A URL e o segredo são configurados pela equipe no backoffice.","tags":["Webhooks"],"responses":{"202":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string"}},"required":["eventId"],"additionalProperties":false},"example":{"eventId":"evt_5d2f8a01-7c39-4b6e-9a14-0e3b7c5d8f26"}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY=''\nPATH_Q='/api/v1/webhooks/test'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'POST\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X POST \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/webhooks/test\";\nconst body = \"\";\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"POST\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"POST\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n  },\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/webhooks/test\"\nbody = \"\"\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"POST\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n}\nres = requests.request(\"POST\", BASE_URL + path, headers=headers)\nprint(res.status_code, res.json())"}]}},"/sandbox/players/{playerId}/kyc/decision":{"post":{"operationId":"sandboxDecideKyc","summary":"Decidir o KYC (somente sandbox)","description":"Simula a decisão da equipe de compliance para o KYC do jogador, para você completar o fluxo em teste sem depender de ninguém. Dispara o webhook `kyc.status_changed`. **Em produção esta rota responde `403 SANDBOX_ONLY`**: lá a decisão é da equipe.","tags":["Sandbox"],"parameters":[{"name":"playerId","in":"path","required":true,"schema":{"description":"Identificador do jogador no BetBackoffice","type":"string","minLength":1},"description":"Identificador do jogador no BetBackoffice","example":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34"},{"name":"Idempotency-Key","in":"header","required":true,"description":"Chave única por intenção (8–128 caracteres). Reenvie a mesma em retentativas.","example":"6f1e2d3c-4b5a-4978-8a9b-0c1d2e3f4a5b","schema":{"type":"string","minLength":8,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["aprovado","reprovado"]},"reason":{"type":"string","minLength":1,"maxLength":200}},"required":["status"]},"example":{"status":"aprovado"}}}},"responses":{"200":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"description":"Situação atual da verificação do jogador","type":"string","enum":["nao_iniciado","pendente","em_analise","documento_solicitado","aprovado","reprovado","expirado"]},"case":{"description":"Caso de KYC mais recente, se houver","anyOf":[{"type":"object","properties":{"id":{"type":"string"},"documentType":{"type":"string","enum":["RG","CNH","Passaporte","Comprovante de residência"]},"status":{"type":"string","enum":["nao_iniciado","pendente","em_analise","documento_solicitado","aprovado","reprovado","expirado"]},"submittedAt":{"type":"string"}},"required":["id","documentType","status","submittedAt"],"additionalProperties":false},{"type":"null"}]}},"required":["status","case"],"additionalProperties":false},"example":{"status":"aprovado","case":{"id":"KYC-9e1f5a3c-6b24-4d78-a0c5-3f8b2d7e1a64","documentType":"RG","status":"aprovado","submittedAt":"2026-09-25T14:05:40.120Z"}}}}},"400":{"description":"Erro: `IDEMPOTENCY_KEY_REQUIRED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"IDEMPOTENCY_KEY_REQUIRED","message":"O cabeçalho Idempotency-Key é obrigatório nesta operação","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`, `SANDBOX_ONLY`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"404":{"description":"Erro: `PLAYER_NOT_FOUND`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"PLAYER_NOT_FOUND","message":"Jogador não encontrado","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"409":{"description":"Erro: `IDEMPOTENCY_CONFLICT`, `IDEMPOTENCY_IN_PROGRESS`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"IDEMPOTENCY_CONFLICT","message":"Idempotency-Key já usada com uma requisição diferente","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY='{\"status\":\"aprovado\"}'\nPATH_Q='/api/v1/sandbox/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/kyc/decision'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'POST\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X POST \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"$BODY\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/sandbox/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/kyc/decision\";\nconst body = JSON.stringify({\n  \"status\": \"aprovado\"\n});\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"POST\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"POST\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n    \"Idempotency-Key\": randomUUID(),\n  },\n  body,\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/sandbox/players/PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34/kyc/decision\"\nbody = json.dumps({\n    \"status\": \"aprovado\"\n}, separators=(\",\", \":\"))\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"POST\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n    \"Idempotency-Key\": str(uuid.uuid4()),\n}\nres = requests.request(\"POST\", BASE_URL + path, headers=headers, data=body)\nprint(res.status_code, res.json())"}]}},"/sandbox/withdrawals/{withdrawalId}/decision":{"post":{"operationId":"sandboxDecideWithdrawal","summary":"Decidir um saque (somente sandbox)","description":"Simula a análise da equipe: `approve` (em análise → aprovado), `reject` (recusa) ou `pay` (aprovado → pago, debitando a carteira). Dispara `withdrawal.status_changed`. **Em produção responde `403 SANDBOX_ONLY`.**","tags":["Sandbox"],"parameters":[{"name":"withdrawalId","in":"path","required":true,"schema":{"type":"string","minLength":1},"example":"WD-c41d9e07-2b6a-4d35-8f10-7e5b9a3c6d82"},{"name":"Idempotency-Key","in":"header","required":true,"description":"Chave única por intenção (8–128 caracteres). Reenvie a mesma em retentativas.","example":"6f1e2d3c-4b5a-4978-8a9b-0c1d2e3f4a5b","schema":{"type":"string","minLength":8,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"decision":{"type":"string","enum":["approve","reject","pay"]}},"required":["decision"]},"example":{"decision":"approve"}}}},"responses":{"200":{"description":"Sucesso","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"playerId":{"type":"string"},"amount":{"description":"Valor decimal em string com 2 casas, ex.: \"100.00\"","type":"string","pattern":"^-?\\d+\\.\\d{2}$"},"currency":{"type":"string"},"method":{"type":"string","enum":["PIX","TED","Cartão","Carteira digital"]},"destination":{"type":"string"},"status":{"description":"under_review: em análise pela equipe; approved: aprovado, aguardando pagamento; paid: pago; rejected: recusado; cancelled: cancelado; failed: falhou","type":"string","enum":["under_review","approved","paid","rejected","cancelled","failed"]},"requestedAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","playerId","amount","currency","method","destination","status","requestedAt","updatedAt"],"additionalProperties":false},"example":{"id":"WD-c41d9e07-2b6a-4d35-8f10-7e5b9a3c6d82","playerId":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34","amount":"50.00","currency":"BRL","method":"PIX","destination":"ana.souza@exemplo.com","status":"approved","requestedAt":"2026-09-25T14:20:15.300Z","updatedAt":"2026-09-25T14:20:15.300Z"}}}},"400":{"description":"Erro: `IDEMPOTENCY_KEY_REQUIRED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"IDEMPOTENCY_KEY_REQUIRED","message":"O cabeçalho Idempotency-Key é obrigatório nesta operação","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"401":{"description":"Erro: `INVALID_CREDENTIALS`, `INVALID_SIGNATURE`, `TIMESTAMP_OUT_OF_RANGE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INVALID_CREDENTIALS","message":"Credenciais inválidas","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"403":{"description":"Erro: `OPERATOR_SUSPENDED`, `FORBIDDEN_IP`, `SANDBOX_ONLY`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"OPERATOR_SUSPENDED","message":"Operador suspenso","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"404":{"description":"Erro: `WITHDRAWAL_NOT_FOUND`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"WITHDRAWAL_NOT_FOUND","message":"Saque não encontrado","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"409":{"description":"Erro: `IDEMPOTENCY_CONFLICT`, `IDEMPOTENCY_IN_PROGRESS`, `INVALID_WITHDRAWAL_STATE`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"IDEMPOTENCY_CONFLICT","message":"Idempotency-Key já usada com uma requisição diferente","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"422":{"description":"Erro: `VALIDATION_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VALIDATION_ERROR","message":"Dados inválidos","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05","details":{"in":"body","issues":[{"path":"cpf","message":"CPF inválido"}]}}}}}},"429":{"description":"Erro: `RATE_LIMITED`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Limite de requisições excedido","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}},"500":{"description":"Erro: `INTERNAL_ERROR`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INTERNAL_ERROR","message":"Erro interno","requestId":"req_8d0c3a9e-5b71-4f24-a6c8-1e9d3f7b2a05"}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (assinado)","source":"# Defina API_BASE_URL (opcional), OPERATOR_KEY e OPERATOR_SECRET no ambiente.\nBODY='{\"decision\":\"approve\"}'\nPATH_Q='/api/v1/sandbox/withdrawals/WD-c41d9e07-2b6a-4d35-8f10-7e5b9a3c6d82/decision'\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | sed 's/^.* //')\nCANONICAL=$(printf 'POST\\n%s\\n%s\\n%s' \"$PATH_Q\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$OPERATOR_SECRET\" -hex | sed 's/^.* //')\n\ncurl -X POST \"${API_BASE_URL:-https://backoffice.betfoguete.bet}$PATH_Q\" \\\n  -H \"X-Operator-Key: $OPERATOR_KEY\" \\\n  -H \"X-Timestamp: $TS\" \\\n  -H \"X-Signature: $SIG\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"$BODY\""},{"lang":"JavaScript","label":"Node.js (assinado)","source":"import { createHash, createHmac, randomUUID } from \"node:crypto\";\n\nconst BASE_URL = process.env.API_BASE_URL ?? \"https://backoffice.betfoguete.bet\";\nconst path = \"/api/v1/sandbox/withdrawals/WD-c41d9e07-2b6a-4d35-8f10-7e5b9a3c6d82/decision\";\nconst body = JSON.stringify({\n  \"decision\": \"approve\"\n});\n\nconst timestamp = String(Math.floor(Date.now() / 1000));\nconst canonical = [\"POST\", path, timestamp, createHash(\"sha256\").update(body).digest(\"hex\")].join(\"\\n\");\nconst signature = createHmac(\"sha256\", process.env.OPERATOR_SECRET).update(canonical).digest(\"hex\");\n\nconst res = await fetch(BASE_URL + path, {\n  method: \"POST\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": process.env.OPERATOR_KEY,\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n    \"Idempotency-Key\": randomUUID(),\n  },\n  body,\n});\nconsole.log(res.status, await res.json());"},{"lang":"Python","label":"Python (assinado)","source":"import hashlib, hmac, json, os, time, uuid\nimport requests\n\nBASE_URL = os.environ.get(\"API_BASE_URL\", \"https://backoffice.betfoguete.bet\")\npath = \"/api/v1/sandbox/withdrawals/WD-c41d9e07-2b6a-4d35-8f10-7e5b9a3c6d82/decision\"\nbody = json.dumps({\n    \"decision\": \"approve\"\n}, separators=(\",\", \":\"))\n\ntimestamp = str(int(time.time()))\ncanonical = \"\\n\".join([\"POST\", path, timestamp, hashlib.sha256(body.encode()).hexdigest()])\nsignature = hmac.new(os.environ[\"OPERATOR_SECRET\"].encode(), canonical.encode(), hashlib.sha256).hexdigest()\n\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"X-Operator-Key\": os.environ[\"OPERATOR_KEY\"],\n    \"X-Timestamp\": timestamp,\n    \"X-Signature\": signature,\n    \"Idempotency-Key\": str(uuid.uuid4()),\n}\nres = requests.request(\"POST\", BASE_URL + path, headers=headers, data=body)\nprint(res.status_code, res.json())"}]}}},"webhooks":{"player.status_changed":{"post":{"operationId":"webhook_player_status_changed","summary":"Situação da conta do jogador mudou","tags":["Webhooks"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador do evento; use para deduplicar entregas repetidas","type":"string"},"type":{"type":"string","const":"player.status_changed"},"createdAt":{"description":"ISO 8601 UTC","type":"string"},"apiVersion":{"type":"string"},"data":{"type":"object","properties":{"playerId":{"type":"string"},"externalId":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["ativo","suspenso","bloqueado","autoexcluido","encerrado","restrito"]},"previousStatus":{"anyOf":[{"type":"string","enum":["ativo","suspenso","bloqueado","autoexcluido","encerrado","restrito"]},{"type":"null"}]}},"required":["playerId","externalId","status","previousStatus"],"additionalProperties":false}},"required":["id","type","createdAt","apiVersion","data"],"additionalProperties":false},"example":{"id":"evt_5d2f8a01-7c39-4b6e-9a14-0e3b7c5d8f26","type":"player.status_changed","createdAt":"2026-09-25T14:09:30.004Z","apiVersion":"1.1.0","data":{"playerId":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34","externalId":"jogador-123","status":"suspenso","previousStatus":"ativo"}}}}},"responses":{"2XX":{"description":"Recebimento confirmado"}}}},"kyc.status_changed":{"post":{"operationId":"webhook_kyc_status_changed","summary":"Situação do KYC mudou","tags":["Webhooks"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador do evento; use para deduplicar entregas repetidas","type":"string"},"type":{"type":"string","const":"kyc.status_changed"},"createdAt":{"description":"ISO 8601 UTC","type":"string"},"apiVersion":{"type":"string"},"data":{"type":"object","properties":{"playerId":{"type":"string"},"externalId":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["nao_iniciado","pendente","em_analise","documento_solicitado","aprovado","reprovado","expirado"]},"previousStatus":{"anyOf":[{"type":"string","enum":["nao_iniciado","pendente","em_analise","documento_solicitado","aprovado","reprovado","expirado"]},{"type":"null"}]}},"required":["playerId","externalId","status","previousStatus"],"additionalProperties":false}},"required":["id","type","createdAt","apiVersion","data"],"additionalProperties":false},"example":{"id":"evt_5d2f8a01-7c39-4b6e-9a14-0e3b7c5d8f26","type":"kyc.status_changed","createdAt":"2026-09-25T14:09:30.004Z","apiVersion":"1.1.0","data":{"playerId":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34","externalId":"jogador-123","status":"aprovado","previousStatus":"em_analise"}}}}},"responses":{"2XX":{"description":"Recebimento confirmado"}}}},"deposit.confirmed":{"post":{"operationId":"webhook_deposit_confirmed","summary":"Depósito confirmado e creditado","tags":["Webhooks"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador do evento; use para deduplicar entregas repetidas","type":"string"},"type":{"type":"string","const":"deposit.confirmed"},"createdAt":{"description":"ISO 8601 UTC","type":"string"},"apiVersion":{"type":"string"},"data":{"type":"object","properties":{"id":{"type":"string"},"playerId":{"type":"string"},"amount":{"description":"Valor decimal em string com 2 casas, ex.: \"100.00\"","type":"string","pattern":"^-?\\d+\\.\\d{2}$"},"currency":{"type":"string"},"method":{"type":"string","enum":["PIX","TED","Cartão","Carteira digital"]},"status":{"type":"string","enum":["pending","confirmed","failed","expired"]},"externalReference":{"anyOf":[{"type":"string"},{"type":"null"}]},"failureReason":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string"},"confirmedAt":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","playerId","amount","currency","method","status","externalReference","failureReason","createdAt","confirmedAt"],"additionalProperties":false}},"required":["id","type","createdAt","apiVersion","data"],"additionalProperties":false},"example":{"id":"evt_5d2f8a01-7c39-4b6e-9a14-0e3b7c5d8f26","type":"deposit.confirmed","createdAt":"2026-09-25T14:09:30.004Z","apiVersion":"1.1.0","data":{"id":"DEP-7b2e4c10-5a93-4f8e-b1d6-0c9a3e7d2f58","playerId":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34","amount":"150.00","currency":"BRL","method":"PIX","status":"confirmed","externalReference":"psp-2026-000123","failureReason":null,"createdAt":"2026-09-25T14:08:02.771Z","confirmedAt":"2026-09-25T14:09:30.004Z"}}}}},"responses":{"2XX":{"description":"Recebimento confirmado"}}}},"deposit.failed":{"post":{"operationId":"webhook_deposit_failed","summary":"Depósito marcado como não concretizado","tags":["Webhooks"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador do evento; use para deduplicar entregas repetidas","type":"string"},"type":{"type":"string","const":"deposit.failed"},"createdAt":{"description":"ISO 8601 UTC","type":"string"},"apiVersion":{"type":"string"},"data":{"type":"object","properties":{"id":{"type":"string"},"playerId":{"type":"string"},"amount":{"description":"Valor decimal em string com 2 casas, ex.: \"100.00\"","type":"string","pattern":"^-?\\d+\\.\\d{2}$"},"currency":{"type":"string"},"method":{"type":"string","enum":["PIX","TED","Cartão","Carteira digital"]},"status":{"type":"string","enum":["pending","confirmed","failed","expired"]},"externalReference":{"anyOf":[{"type":"string"},{"type":"null"}]},"failureReason":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string"},"confirmedAt":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","playerId","amount","currency","method","status","externalReference","failureReason","createdAt","confirmedAt"],"additionalProperties":false}},"required":["id","type","createdAt","apiVersion","data"],"additionalProperties":false},"example":{"id":"evt_5d2f8a01-7c39-4b6e-9a14-0e3b7c5d8f26","type":"deposit.failed","createdAt":"2026-09-25T14:09:30.004Z","apiVersion":"1.1.0","data":{"id":"DEP-7b2e4c10-5a93-4f8e-b1d6-0c9a3e7d2f58","playerId":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34","amount":"150.00","currency":"BRL","method":"PIX","status":"failed","externalReference":"psp-2026-000123","failureReason":"pagamento expirou no PSP","createdAt":"2026-09-25T14:08:02.771Z","confirmedAt":null}}}}},"responses":{"2XX":{"description":"Recebimento confirmado"}}}},"withdrawal.status_changed":{"post":{"operationId":"webhook_withdrawal_status_changed","summary":"Situação do saque mudou","tags":["Webhooks"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador do evento; use para deduplicar entregas repetidas","type":"string"},"type":{"type":"string","const":"withdrawal.status_changed"},"createdAt":{"description":"ISO 8601 UTC","type":"string"},"apiVersion":{"type":"string"},"data":{"type":"object","properties":{"playerId":{"type":"string"},"externalId":{"anyOf":[{"type":"string"},{"type":"null"}]},"withdrawalId":{"type":"string"},"amount":{"type":"string"},"currency":{"type":"string"},"status":{"type":"string","enum":["under_review","approved","paid","rejected","cancelled","failed"]},"previousStatus":{"anyOf":[{"type":"string","enum":["under_review","approved","paid","rejected","cancelled","failed"]},{"type":"null"}]}},"required":["playerId","externalId","withdrawalId","amount","currency","status","previousStatus"],"additionalProperties":false}},"required":["id","type","createdAt","apiVersion","data"],"additionalProperties":false},"example":{"id":"evt_5d2f8a01-7c39-4b6e-9a14-0e3b7c5d8f26","type":"withdrawal.status_changed","createdAt":"2026-09-25T14:09:30.004Z","apiVersion":"1.1.0","data":{"playerId":"PLU-3f1c9a2e-8d4b-4e6a-9c1d-2b7e5f0a1c34","externalId":"jogador-123","withdrawalId":"WD-c41d9e07-2b6a-4d35-8f10-7e5b9a3c6d82","amount":"50.00","currency":"BRL","status":"approved","previousStatus":"under_review"}}}}},"responses":{"2XX":{"description":"Recebimento confirmado"}}}},"webhook.test":{"post":{"operationId":"webhook_webhook_test","summary":"Evento de teste (POST /webhooks/test)","tags":["Webhooks"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador do evento; use para deduplicar entregas repetidas","type":"string"},"type":{"type":"string","const":"webhook.test"},"createdAt":{"description":"ISO 8601 UTC","type":"string"},"apiVersion":{"type":"string"},"data":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}},"required":["id","type","createdAt","apiVersion","data"],"additionalProperties":false},"example":{"id":"evt_5d2f8a01-7c39-4b6e-9a14-0e3b7c5d8f26","type":"webhook.test","createdAt":"2026-09-25T14:09:30.004Z","apiVersion":"1.1.0","data":{"message":"Webhook de teste do BetBackoffice"}}}}},"responses":{"2XX":{"description":"Recebimento confirmado"}}}}},"components":{"securitySchemes":{"OperatorKey":{"type":"apiKey","in":"header","name":"X-Operator-Key","description":"Chave da credencial do operador."},"Timestamp":{"type":"apiKey","in":"header","name":"X-Timestamp","description":"Epoch em segundos (±5 min)."},"Signature":{"type":"apiKey","in":"header","name":"X-Signature","description":"hex(HMAC-SHA256(secret, METODO\\nCAMINHO?QUERY\\nTIMESTAMP\\nSHA256_HEX(corpo)))."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"description":"Código estável do erro","type":"string"},"message":{"type":"string"},"requestId":{"description":"Identificador da requisição, para suporte","type":"string"},"details":{}},"required":["code","message","requestId"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}