Appearance
Authentication
UltimaLotto supports multiple authentication methods for different use cases.
API Key Authentication
For server-to-server SDK integration, use your API key in the X-Ultima-Key header.
API keys are formatted as ulk_ followed by 32 hex characters (e.g., ulk_a1b2c3d4e5f6...).
Example
typescript
const response = await fetch("https://api.ultimalotto.com/api/operator/me", {
headers: {
"X-Ultima-Key": "ulk_your_api_key_here",
},
});Using the SDK
The Operator SDK automatically handles API key authentication:
typescript
const client = new CoordinatorClient({
coordinatorUrl: "https://api.ultimalotto.com",
apiKey: "ulk_your_api_key_here",
maxRetries: 3,
requestTimeoutMs: 10_000,
});JWT Authentication
For browser-based dashboards and portals, use JWT tokens. Access tokens expire in 15 minutes; refresh tokens last 7 days and are single-use.
Login Flow
typescript
// Exchange API key for JWT pair
const loginRes = await fetch("https://api.ultimalotto.com/api/auth/operator/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ apiKey: "ulk_your_api_key_here" }),
});
const { accessToken, refreshToken, expiresIn } = await loginRes.json();Using Access Token
typescript
const response = await fetch("https://api.ultimalotto.com/api/operator/me", {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});Refresh Token
typescript
const refreshRes = await fetch("https://api.ultimalotto.com/api/auth/refresh", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ refreshToken }),
});
const { accessToken, refreshToken } = await refreshRes.json();
// Old refresh token is revoked; use the new one for next refreshLogout
typescript
await fetch("https://api.ultimalotto.com/api/auth/logout", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ refreshToken }),
});Webhook Signature Verification
All webhooks are signed with HMAC-SHA256. Verify the X-Ultima-Signature header before processing.
Verification
typescript
import { createHmac } from "node:crypto";
function verifyWebhookSignature(
rawBody: string,
signature: string,
apiKey: string
): boolean {
const expected = createHmac("sha256", apiKey)
.update(rawBody)
.digest("hex");
return signature === expected;
}
// In your webhook handler
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
const signature = req.headers["x-ultima-signature"] as string;
const rawBody = req.body.toString();
if (!verifyWebhookSignature(rawBody, signature, process.env.ULTIMA_API_KEY!)) {
res.status(401).send("Invalid signature");
return;
}
const payload = JSON.parse(rawBody);
// Process payload...
res.status(200).send("OK");
});Important
Always use the raw request body for signature verification. Parsing JSON or modifying the body will invalidate the signature.