TCG Scanner API
Integrate card scanning and detection into your applications. Perfect for live pack opening platforms, inventory management, and streaming overlays.
https://deckardgains.abacusai.app/api/v1Quick Start
To use the API, you'll need an API key. Generate one by logging into your account and creating a key.
1. Generate an API Key
# Using your session cookie (log in first)
curl -X POST https://deckardgains.abacusai.app/api/v1/keys \
-H "Content-Type: application/json" \
-H "Cookie: your-session-cookie" \
-d '{"name": "My App", "permissions": ["scan:read", "scan:write", "webhook:manage"]}'2. Make API Requests
# Create a scan session
curl -X POST https://deckardgains.abacusai.app/api/v1/sessions \
-H "Authorization: Bearer tcgs_your_api_key" \
-H "Content-Type: application/json" \
-d '{"name": "Pack Opening Stream", "tcg_type": "MTG"}'Authentication
All API requests require authentication via an API key passed in the Authorization header:
Authorization: Bearer tcgs_your_api_key_herescan:read- Read sessions and detected cardsscan:write- Create sessions and add cardswebhook:manage- Register and manage webhooks*- Full access
API Key Management
These endpoints require session authentication (you must be logged in).
Scan Sessions
Sessions group detected cards together. Create a session for each pack opening, box break, or scanning event.
Card Detection
Add detected cards to a session. Supports batch additions for efficiency.
Webhooks
Receive real-time notifications when cards are detected or sessions complete. Perfect for stream overlays and leaderboards.
Available Events
session.started- Fired when a new session beginssession.completed- Fired when a session is marked completecard.detected- Fired for each individual card detectioncard.batch_detected- Fired when multiple cards are added at once
Webhook Payload Format
// Headers sent with each webhook
X-TCG-Scanner-Signature: t=1708527600,v1=abc123...
X-TCG-Scanner-Event: card.detected
Content-Type: application/json
// Example payload for card.detected
{
"event": "card.detected",
"timestamp": "2026-02-21T12:00:00.000Z",
"data": {
"session_id": "clxyz789...",
"card": {
"id": "card_123",
"name": "Black Lotus",
"tcg_type": "MTG",
"set_name": "Alpha",
"rarity": "Rare",
"price_usd": 50000.00,
"confidence": 0.98,
"quantity": 1,
"image_url": "https://i.ytimg.com/vi/IS1PlCmW4RM/hq720.jpg?sqp=-oaymwEhCK4FEIIDSFryq4qpAxMIARUAAAAAGAElAADIQj0AgKJD&rs=AOn4CLBXJ_rpW6PNnvTEXptCfgcln0VkDA"
}
}
}Verifying Webhook Signatures
Always verify webhook signatures to ensure requests are from the TCG Scanner.
import crypto from 'crypto';
function verifyWebhookSignature(payload, signature, secret) {
const [timestampPart, signaturePart] = signature.split(',');
const timestamp = timestampPart.split('=')[1];
const expectedSig = signaturePart.split('=')[1];
const signedPayload = `${timestamp}.${payload}`;
const computedSig = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
// Timing-safe comparison
return crypto.timingSafeEqual(
Buffer.from(expectedSig),
Buffer.from(computedSig)
);
}Full Integration Example
Here's a complete example of integrating the scanner with a pack opening stream:
// 1. Start a session when the stream begins
const session = await fetch('https://deckardgains.abacusai.app/api/v1/sessions', {
method: 'POST',
headers: {
'Authorization': 'Bearer tcgs_your_api_key',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Friday Night Box Break',
tcg_type: 'MTG',
metadata: { stream_id: 'twitch_123', shop: 'Card Kingdom' }
})
}).then(r => r.json());
const sessionId = session.data.session_id;
// 2. When scanner detects a card, add it to the session
async function onCardDetected(cardData) {
await fetch(`https://deckardgains.abacusai.app/api/v1/sessions/${sessionId}/cards`, {
method: 'POST',
headers: {
'Authorization': 'Bearer tcgs_your_api_key',
'Content-Type': 'application/json'
},
body: JSON.stringify({
cards: [{
name: cardData.name,
tcg_type: 'MTG',
set_name: cardData.set,
rarity: cardData.rarity,
price_usd: cardData.price,
confidence: cardData.confidence,
image_url: cardData.image
}]
})
});
}
// 3. Mark session complete when stream ends
await fetch(`https://deckardgains.abacusai.app/api/v1/sessions/${sessionId}`, {
method: 'PATCH',
headers: {
'Authorization': 'Bearer tcgs_your_api_key',
'Content-Type': 'application/json'
},
body: JSON.stringify({ status: 'COMPLETED' })
});
// 4. Get final results
const results = await fetch(`https://deckardgains.abacusai.app/api/v1/sessions/${sessionId}`, {
headers: { 'Authorization': 'Bearer tcgs_your_api_key' }
}).then(r => r.json());
console.log(`Total value: $${results.data.total_value}`);
console.log(`Cards pulled: ${results.data.total_cards}`);Rate Limits
- Default: 1,000 requests per hour per API key
- Webhook deliveries: Automatic retry with exponential backoff (max 3 attempts)
- Webhooks disabled: After 10 consecutive failures, webhooks are automatically deactivated
Error Responses
| Status | Meaning |
|---|---|
400 | Bad Request - Invalid parameters |
401 | Unauthorized - Missing or invalid API key |
403 | Forbidden - Missing required permission |
404 | Not Found - Resource doesn't exist |
429 | Too Many Requests - Rate limit exceeded |
500 | Internal Server Error |
{
"error": "Missing permission: scan:write",
"status": 403
}