API Reference
Public API v1 + Internal endpoints
Base URL
Development: http://localhost:3002
Production: https://api.positlabs.io
Authentication Live
The API uses API keys for authentication. Include your key in the Authorization header (preferred) or X-API-Key header:
curl -H "Authorization: Bearer pk_bas_xxxxx" https://api.positlabs.io/api/v1/wallets/...
# or
curl -H "X-API-Key: pk_bas_xxxxx" https://api.positlabs.io/api/v1/wallets/...
API Key Features
- IP Whitelisting — Restrict key usage to specific IP addresses
- Custom Rate Limits — Override tier defaults per key
- Key Rotation — Rotate keys with configurable grace period (old key works during transition)
- Expiration — Set expiration dates with automatic alerts (7/3/1 day warnings)
- Audit Logging — All requests logged with endpoint statistics
- Scopes — Fine-grained permissions (read, write, admin)
Rate Limits
| Tier | Requests/Min | Requests/Day |
|---|---|---|
| Basic | 60 | 10,000 |
| Pro | 300 | 100,000 |
| Enterprise | 1,000 | 1,000,000 |
Rate limits use a sliding window algorithm. Per-minute limits reset after 60 seconds of the first request in the window.
Rate Limit Headers
Every API response includes rate limit information:
| Header | Description |
|---|---|
X-RateLimit-Limit-Minute |
Max requests per minute for this key |
X-RateLimit-Remaining-Minute |
Remaining requests in current minute window |
X-RateLimit-Limit-Day |
Max requests per day for this key |
X-RateLimit-Remaining-Day |
Remaining requests today (resets at midnight UTC) |
X-RateLimit-Reset-Minute |
ISO timestamp when minute window resets |
X-RateLimit-Reset-Day |
ISO timestamp when daily limit resets |
Retry-After |
Seconds to wait (only on 429 responses) |
Public API v1 OpenAPI 3.1
Full OpenAPI spec available at /api/v1/openapi.json
Wallet Intelligence
Get wallet rating, score, decay state, and labels.
{
"address": "7xKp...",
"chain": "solana",
"score": 87.5,
"decayState": "sharp",
"flaggedAt": "2025-01-15T00:00:00Z",
"labels": [
{ "label": "smart_money", "confidence": 0.92 },
{ "label": "early_buyer", "confidence": 0.88 }
],
"metrics": {
"winRate": 72.5,
"avgReturn": 245.8,
"totalTrades": 156,
"profitableTrades": 113
}
}
Get top-ranked wallets by score.
{
"wallets": [
{
"rank": 1,
"address": "7xKp...",
"chain": "solana",
"score": 94.2,
"decayState": "sharp",
"labels": ["smart_money", "whale"]
}
],
"total": 1250
}
Search wallets by address prefix or label.
Cohorts & Analytics
Get cohort retention metrics.
{
"cohorts": [
{
"month": "2025-01",
"totalFlagged": 156,
"sharpCount": 89,
"fadingCount": 45,
"deadCount": 22,
"retentionRate": 57.1
}
]
}
Get detailed cohort data with decay curve.
Webhooks
Subscribe to webhook events.
{
"url": "https://your-server.com/webhook",
"events": [
"wallet.rating.updated",
"wallet.decay_state.changed",
"alert.copy_detected"
],
"secret": "your_webhook_secret"
}
wallet.rating.updated- Score recalculatedwallet.decay_state.changed- sharp → fading → deadcohort.snapshot.created- New cohort dataalert.wallet.flagged- New wallet flaggedalert.copy_detected- Copy trading detected
List your webhook subscriptions.
Unsubscribe from a webhook.
Exports
Generate signed export URLs for data downloads.
{
"type": "transactions" | "tax_report" | "positions",
"format": "csv" | "json" | "pdf",
"walletAddress": "7xKp...",
"chain": "solana",
"dateRange": {
"start": "2025-01-01",
"end": "2025-12-31"
}
}
Internal Endpoints
Parser
Parse transactions for a wallet address. Fetches from chain RPC, parses swaps, and calculates cost basis.
{
"success": true,
"address": "7xKp...",
"chain": "solana",
"stats": {
"transactionsFetched": 500,
"swapsParsed": 234,
"failuresSkipped": 266,
"parseRate": "46.8%",
"durationMs": 15234,
"pricingSource": "jupiter"
},
"costBasis": {
"realisedPnl": 1520.50,
"lotsCreated": 89,
"positionsCount": 12
},
"swaps": [...],
"venueBreakdown": { "jupiter": 145, "raydium_amm": 67 },
"botBreakdown": { "photon": 45, "direct": 189 }
}
Dashboard
List all connected wallets with summary stats.
{
"success": true,
"wallets": [
{
"id": "uuid",
"address": "7xKp...",
"label": "Main Trading",
"chain": "solana",
"syncState": "live",
"lastSync": "2026-06-04T12:00:00Z",
"transactionCount": 272,
"totalValue": 32529.98,
"isActive": true
}
]
}
Add a new wallet to track.
Get current positions for a specific wallet (spot + perpetual).
Get tax report data for a specific year.
{
"success": true,
"year": 2025,
"summary": {
"shortTermGains": 1700,
"shortTermLosses": 540,
"longTermGains": 4900,
"longTermLosses": 0,
"netShortTerm": 1160,
"netLongTerm": 4900,
"totalTaxableGain": 6060
},
"taxEvents": [...]
}
Intelligence
Classify a wallet and generate labels.
Get copy trading detection alerts.
Health Check
API health check endpoint.
{
"status": "ok",
"version": "1.0.0",
"timestamp": "2026-06-05T12:00:00.000Z",
"chains": {
"solana": "ok",
"base": "ok",
"hyperliquid": "ok"
}
}
Webhook Signature Verification
All outgoing webhooks are signed using HMAC-SHA256. Verify the signature using your webhook secret:
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// In your webhook handler:
const signature = req.headers['x-webhook-signature'];
if (!verifyWebhook(req.body, signature, WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
API Key Management
List all API keys for the authenticated user.
{
"keys": [
{
"id": "uuid",
"name": "Production Bot",
"keyPrefix": "pk_bas_xxxx",
"tier": "basic",
"scopes": ["read"],
"rateLimitPerMinute": 60,
"rateLimitPerDay": 10000,
"requestCountToday": 1234,
"lastUsedAt": "2026-06-05T10:30:00Z",
"allowedIps": ["1.2.3.4"],
"expiresAt": null,
"createdAt": "2026-01-01T00:00:00Z"
}
]
}
Create a new API key. The full key is only shown once.
{
"name": "My API Key",
"description": "Optional description",
"tier": "basic",
"scopes": ["read"],
"allowedIps": ["1.2.3.4", "5.6.7.8"],
"customRateLimitPerMinute": 30,
"customRateLimitPerDay": 5000,
"expiresInDays": 90,
"tags": ["production", "bot"]
}
{
"key": { ... },
"secret": "pk_bas_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
Rotate an API key. Creates a new key and optionally keeps the old key working during a grace period.
{
"gracePeriodHours": 24
}
{
"newKey": { ... },
"newSecret": "pk_bas_yyyyyyyyyyyyyyyyyyyyyyyyyyyy",
"oldKeyDisabledAt": "2026-06-06T12:00:00Z"
}
Revoke an API key immediately.
Get usage statistics for an API key.
{
"endpoints": [
{
"endpointPath": "/api/v1/wallets/rating",
"requestCount": 5420,
"successCount": 5400,
"errorCount": 20,
"avgResponseTimeMs": 145
}
],
"totalRequests": 12500,
"totalErrors": 42,
"avgResponseTime": 132
}
Error Responses
{
"success": false,
"error": "Error message description",
"code": "INVALID_ADDRESS"
}
Error Codes
| HTTP | Code | Description |
|---|---|---|
| 400 | INVALID_ADDRESS | Invalid wallet address format |
| 400 | INVALID_CHAIN | Unsupported chain |
| 401 | API_KEY_REQUIRED | No API key provided in request |
| 401 | INVALID_API_KEY | API key is invalid, expired, or revoked |
| 401 | IP_NOT_ALLOWED | Request IP not in key's whitelist |
| 403 | INSUFFICIENT_SCOPES | API key lacks required permissions |
| 404 | NOT_FOUND | Resource not found |
| 429 | RATE_LIMIT_EXCEEDED | Rate limit exceeded (check Retry-After header) |
| 500 | INTERNAL_ERROR | Internal server error |
Rate limit errors include additional context:
{
"error": "Rate limit exceeded",
"code": "RATE_LIMIT_EXCEEDED",
"limitType": "minute",
"limits": {
"minute": { "limit": 60, "remaining": 0, "resetAt": "2026-06-05T12:01:00Z" },
"day": { "limit": 10000, "remaining": 8500, "resetAt": "2026-06-06T00:00:00Z" }
}
}