Skip to main content

Before You Debug

Most integration issues come from one of four causes:
  • Mixing devnet and mainnet values.
  • Signing the wrong activation message.
  • Using an expired or missing guest JWT.
  • Deriving validation PDAs from a timestamp that does not match the proof payload.
Use one network consistently for every value:
NetworkProgram IDGuest JWT URLActivation URLAPI Base
Mainnet9ExbZjAapQww1vfcisDmrngPinHTEfpjYRWMunJgcKaAhttps://txline.txodds.com/auth/guest/starthttps://txline.txodds.com/api/token/activatehttps://txline.txodds.com/api/
Devnet6pW64gN1s2uqjHkn1unFeEjAwJkPGHoppGvS715wyP2Jhttps://txline-dev.txodds.com/auth/guest/starthttps://txline-dev.txodds.com/api/token/activatehttps://txline-dev.txodds.com/api/
Never share your guest JWT, activated API token, wallet secret key, or unredacted request headers in public support channels.

Activation Checklist

Before calling /api/token/activate, confirm:
  • The on-chain subscribe(serviceLevelId, durationWeeks) transaction is confirmed.
  • The txSig is from the same network as the activation endpoint.
  • The guest JWT came from the same network host.
  • The signing wallet is the same wallet that submitted the subscribe transaction.
  • walletSignature is a base64-encoded detached signature.
  • leagues is [] for the standard free World Cup and International Friendlies bundle.
The activation message is:
${txSig}:${selectedLeagues.join(",")}:${jwt}
For selectedLeagues = [], sign:
${txSig}::${jwt}

Runnable Example Checklist

When running the repository examples in examples/devnet, confirm:
  • You are using Node.js 20 or newer. The current lockfile resolves eventsource@4.1.0, which requires node >=20.0.0.
  • ANCHOR_PROVIDER_URL points to https://api.devnet.solana.com.
  • TOKEN_MINT_ADDRESS is the devnet TxL mint 4Zao8ocPhmMgq7PdsYWyxvqySMGx7xb9cMftPMkEokRG.
  • The script imports the devnet IDL/types from examples/devnet/idl and examples/devnet/types.
  • The wallet in ANCHOR_WALLET has enough devnet SOL for subscription transactions and account rent.
  • Fixed fixtureId and seq pairs in example scripts are demo fixtures. For production, derive them from an observed score record.
  • Final match outcome settlement should use scores records with action=game_finalised, statusId=100, and period=100.
  • Fixture examples should expect the backward-compatible GameState field; current values are 1 for scheduled and 6 for cancelled.

Common Errors

SymptomLikely causeWhat to check
Example script fails before connecting to TxLINENode runtime or environment variables do not match the current examplesUse Node.js 20+, set ANCHOR_PROVIDER_URL, ANCHOR_WALLET, and TOKEN_MINT_ADDRESS, then run from the repository root
504 Gateway Timeout from /api/token/activateOften a network mismatch, such as a devnet transaction sent to the mainnet activation host, or a backend timeoutConfirm txSig, guest JWT, program ID, and activation URL are all mainnet or all devnet
403 signature verification failedWrong signing preimage, wrong wallet, wrong signature encoding, or wrong JWT hostSign the exact message string, use the subscribe wallet, send base64 detached signature, and use the matching network JWT
401 Unauthorized on data endpointsMissing or expired guest JWTRequest a fresh guest JWT from the same host and retry with the same X-Api-Token
403 Access denied on data endpointsInvalid API token, expired subscription, wrong network token, or insufficient subscription permissionsConfirm the X-Api-Token came from the same network and subscription bundle
Invalid public key inputPlaceholder value was not replaced with a real Solana public keyReplace all placeholders with the program ID, TxL mint, and wallet public key for the selected network
SSE connection opens but no data messages arriveThe stream can be healthy even when no covered fixture is actively producing updatesCheck the Schedule, keep the stream open, or use historical endpoints for completed fixtures
/api/scores/stat-validation called with seq=0 or a random seqThe sequence was treated as a placeholder instead of coming from a real score recordGet a score record from snapshot, updates, historical data, or the scores stream, then pass that record’s observed Seq or seq value
InvalidMainTreeProof during validationTimestamp, epoch day PDA, proof decoding, or fixture/update selection mismatchDerive daily_scores_roots from the same timestamp passed to validateStat, decode hashes to exactly 32 bytes, and verify you are using the intended fixture and sequence
validateStatV2 strategy checks the wrong valuestatKeys order and positional strategy indexes were mixed upKeep the requested statKeys order next to the strategy. index, indexA, indexB, and statIndex refer to statsToProve[0..N], not to the numeric stat key itself
Final outcome settlement uses the wrong phaseThe client selected an in-running or period-specific record instead of the match finalisation recordUse a scores record with action=game_finalised, statusId=100, and period=100

Auth Headers

Most data endpoints require both credentials:
HeaderValue
AuthorizationBearer <guest-jwt> from /auth/guest/start
X-Api-TokenActivated API token from /api/token/activate
If the guest JWT expires, request a new JWT from the same network host. You do not need to reactivate the API token unless the subscription or token itself is invalid.

Stream Debugging

Server-Sent Events streams can send connection-level events, heartbeats, or no data for a period when there is no active covered fixture update. When debugging streams:
  • Use the matching host: https://txline.txodds.com/api/... for mainnet or https://txline-dev.txodds.com/api/... for devnet.
  • Send both Authorization and X-Api-Token.
  • Set Accept: text/event-stream.
  • Treat an open connection with heartbeats as a live connection, not necessarily a data failure.
  • Check Scores Schedule for active or upcoming covered fixtures.
  • Use /api/scores/historical/{fixtureId} for a full replay when the fixture is already historical and within the supported historical window.

Validation Debugging

For score validation, keep the API proof, PDA derivation, and on-chain call aligned:
const targetTs = validation.summary.updateStats.minTimestamp;
const epochDay = Math.floor(targetTs / (24 * 60 * 60 * 1000));

const [dailyScoresPda] = PublicKey.findProgramAddressSync(
  [
    Buffer.from("daily_scores_roots"),
    new BN(epochDay).toArrayLike(Buffer, "le", 2),
  ],
  program.programId
);
Pass the same targetTs into validateStat, and make sure every proof hash is decoded to exactly 32 bytes before passing it to Anchor. Use a real score record sequence for /api/scores/stat-validation; seq=0 is not valid. For settlement conditions tied to a period result, choose a record whose phase or status represents that completed period. An in-running record proves the condition at that moment, not the final result of the period. For final match outcome settlement, use action=game_finalised records. Current devnet and mainnet releases set both statusId and period to 100 for those records. For V2 validation, request multiple stats with statKeys=1,2,... and keep that order stable when building statsToProve, statProofs, and strategy predicates. See Runnable Devnet Examples for complete validateStatV2 scripts. For a first sanity check, use an exact predicate against the returned stat value if your response shape includes validation.statToProve.value:
const predicate = {
  threshold: validation.statToProve.value,
  comparison: { equalTo: {} },
};
After this exact predicate succeeds, replace it with your application-specific predicate.

Support Template

When opening a support ticket, include:
  • Network: mainnet or devnet.
  • Endpoint path and HTTP status.
  • Program ID used.
  • Service level ID and duration.
  • Redacted transaction signature prefix/suffix.
  • For activation: the selected leagues array and whether the signed message was txSig::jwt.
  • For validation: fixture ID, sequence number, stat key, timestamp used, epoch day, and PDA.
  • For V2 validation: the full statKeys list and the strategy indexes being checked.
  • For final outcome validation: whether the selected score record had action=game_finalised, statusId=100, and period=100.
  • For fixture validation: the fixture GameState value.
  • Response body with secrets removed.
Do not include:
  • Guest JWT.
  • X-Api-Token.
  • Wallet secret key.
  • Full private request logs with authorization headers.