https://api.newfanspro.com/v1Integrate with NewFans Pro in 3 steps
Generate your API keys from the Settings dashboard. You'll get both a secret key and a publishable key.
Set up webhook endpoints to receive real-time events when things happen in your account.
Start integrating with our REST API endpoints. Use our SDKs or call the API directly.
https://api.newfanspro.com/v1Secure your API requests with Bearer token authentication
NewFans Pro uses API keys for authentication. Include your key in the Authorization header. Manage keys in Settings → API.
Use for server-side requests only. Never expose in client code or version control.
sk_live_xxxxxxxxxxxxxSafe for client-side code. Limited to public read-only operations.
pk_live_xxxxxxxxxxxxxAPI keys can be scoped to specific permissions. Restrict keys to only the operations your integration needs.
| Scope | Description |
|---|---|
| drops:read | List and retrieve drops |
| drops:write | Create, update, and publish drops |
| fans:read | List and retrieve fan profiles |
| orders:read | List and retrieve orders |
| orders:write | Process refunds |
| nfc:read | List tags, batches, analytics |
| nfc:write | Create batches and manage tags |
| analytics:read | Access all analytics data |
| messaging:write | Send push notifications & campaigns |
| ai:write | Use AI generation features |
curl https://api.newfanspro.com/v1/drops \\
-H "Authorization: Bearer sk_live_your_api_key" \\
-H "Content-Type: application/json"48 endpoints across 10 resources
All list endpoints support cursor-based pagination
Use page and per_page query parameters. Default page size is 25, maximum is 100.
| page | Page number (starting from 1) |
| per_page | Items per page (1-100, default: 25) |
| sort | Sort field (varies by endpoint) |
| order | Sort direction: asc or desc |
{
"success": true,
"data": {
"drops": [...],
"total": 152,
"page": 2,
"per_page": 25,
"has_more": true,
"total_pages": 7
}
}Receive real-time HTTP notifications for 30 event types
Configure endpoints in Settings → Webhooks. We retry failed deliveries up to 3 times with exponential backoff.
drop.createdA new drop was createddrop.publishedA drop was published and went livedrop.updatedA drop's configuration was updateddrop.archivedA drop was archivedorder.createdA new order was placedorder.completedPayment was captured and order completedorder.refundedAn order was fully or partially refundedorder.disputedA payment dispute was openedfan.createdA new fan signed up or was addedfan.subscribedA fan subscribed to email/SMS updatesfan.unsubscribedA fan unsubscribed from updatesfan.birthdayA fan's birthday is todaynfc.claimedAn NFC tag was successfully claimednfc.scannedAn NFC tag was scanned (not necessarily claimed)nfc.batch_createdA new NFC batch was generatedentitlement.grantedContent access was granted to a fanentitlement.revokedContent access was revokedentitlement.expiredTime-limited access expireddispute.createdA payment dispute was openeddispute.resolvedA dispute was resolveddispute.evidence_requiredEvidence submission deadline approachingcollaborator.invitedA collaborator invitation was sentcollaborator.acceptedA collaborator accepted their invitecollaborator.declinedA collaborator declined their invitepayout.initiatedA payout was initiatedpayout.completedA payout was completed successfullypayout.failedA payout attempt failedfanclub.member_joinedA fan joined the fan clubfanclub.member_leftA fan left the fan clubfanclub.request_pendingA new join request is pending{
"id": "evt_1234567890",
"type": "order.completed",
"api_version": "v1",
"created": 1679529600,
"livemode": true,
"data": {
"object": {
"id": "ord_abc123",
"amount": 2999,
"currency": "usd",
"fan_id": "fan_xyz789",
"drop_id": "drop_def456",
"status": "completed"
},
"previous_attributes": {}
}
}All webhook requests include a x-newfans-signature header.
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const timestamp = signature.split(',')[0].split('=')[1];
const receivedSig = signature.split(',')[1].split('=')[1];
const signedPayload = `${timestamp}.${payload}`;
const expectedSig = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(receivedSig),
Buffer.from(expectedSig)
);
}Fair usage limits to maintain service quality
req/min
req/min
req/min
Contact us
X-RateLimit-LimitMaximum requests per window1000X-RateLimit-RemainingRequests remaining985X-RateLimit-ResetWindow reset (Unix timestamp)1704067200Retry-AfterSeconds until retry (429 only)45async function apiCallWithRetry(fn, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fn();
if (response.status !== 429) return response;
const retryAfter = parseInt(
response.headers.get('Retry-After') || String(Math.pow(2, attempt) * 1000)
);
await new Promise(r => setTimeout(r, retryAfter));
}
throw new Error('Max retries exceeded');
}Conventional HTTP codes with structured error responses
{
"success": false,
"error": {
"type": "validation_error",
"code": "parameter_invalid",
"message": "The 'amount' parameter must be a positive integer.",
"param": "amount",
"details": {
"received": -5,
"expected": "positive integer"
}
},
"request_id": "req_abc123xyz"
}| Type | Description |
|---|---|
| authentication_error | Invalid or missing API key |
| authorization_error | Key lacks required scope |
| validation_error | Request parameters invalid |
| not_found | Resource doesn't exist |
| rate_limit_error | Too many requests |
| plan_limit_error | Feature requires upgrade |
| insufficient_credits | Not enough AI credits |
| server_error | Internal server error |
request_id when contacting support to help debug issues.Official client libraries for popular languages
npm install @newfans/sdkpip install newfansnpm install @newfans/sdkimport { NewFansClient } from '@newfans/sdk';
const client = new NewFansClient({
apiKey: process.env.NEWFANS_API_KEY,
});
// List drops
const drops = await client.drops.list({ status: 'active' });
// Create a drop
const newDrop = await client.drops.create({
title: 'New Album',
type: 'digital_album',
pricing: { type: 'fixed', amount: 9.99 }
});
// Send push notification
await client.messaging.sendPush({
audience: 'all_fans',
title: 'New Drop!',
body: 'Check out my latest release'
});Common integration patterns and recipes
Full workflow: create, upload media, then publish
// 1. Create the drop
const drop = await fetch('https://api.newfanspro.com/v1/drops', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_xxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: 'Summer Album 2024',
type: 'digital_album',
pricing: { type: 'fixed', amount: 14.99 },
settings: { show_in_pocket: true }
})
});
const { data: { id: dropId } } = await drop.json();
// 2. Publish when ready
await fetch(`https://api.newfanspro.com/v1/drops/${dropId}/publish`, {
method: 'POST',
headers: { 'Authorization': 'Bearer sk_live_xxx' },
body: JSON.stringify({ notify_fans: true })
});Create 500 NFC codes for a live show
const batch = await fetch('https://api.newfanspro.com/v1/nfc/batches', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_xxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
count: 500,
drop_id: 'drop_abc123',
prefix: 'SHOW2024',
metadata: { event: 'Summer Tour 2024' }
})
});
const { data: { batch: newBatch } } = await batch.json();
console.log('Download codes:', newBatch.csv_url);Fetch and export time-series revenue data
const analytics = await fetch(
'https://api.newfanspro.com/v1/analytics/revenue?' + new URLSearchParams({
start_date: '2024-01-01',
end_date: '2024-12-31',
group_by: 'month'
}),
{ headers: { 'Authorization': 'Bearer sk_live_xxx' } }
);
const { data } = await analytics.json();
// Or use the export endpoint
const csv = await fetch(
'https://api.newfanspro.com/v1/analytics/export?format=csv&report=revenue',
{ headers: { 'Authorization': 'Bearer sk_live_xxx' } }
);Track API updates, new endpoints, and improvements