Before you begin, make sure you have the following ready. The entire flow takes under 10 minutes on a clean machine.
Node.js 18+
Required by the SDK. Check: node --version
Aforo Account
Sign up for an Aforo account — free sandbox included
API Key
sk_test_… from Workspace Admin → API Keys (workspace scope rides on the key)
A billable unit
At least one metric (billable unit) defined in your dashboard
PRO TIP
You do not need a gateway plugin to start. The Node.js SDK sends events directly to Aforo's ingest endpoint. Deploy the gateway plugin later when you're ready to go to production.
Install the Aforo metering SDK into your project. The SDK handles batching, retries, and async flushing so your API latency is never impacted.
terminal
npm install @aforo/metering
INFO
Not yet on the public npm registry — until it's published, install from source: clone the Aforo metering SDK repo, then in its node package run npm install && npm run build && npm pack and install the resulting tarball. Same package, same API.
If you use Yarn or pnpm, the package name is the same:
Create a single client instance and reuse it across your application. The client batches events internally and flushes every 5 seconds or when the buffer reaches 50 events — whichever comes first.
aforo-client.ts
import { AforoClient } from '@aforo/metering';
export const aforo = new AforoClient({
apiKey: process.env.AFORO_API_KEY!, // sk_test_… or sk_live_…; workspace scope rides on the key
// Optional — defaults to https://ingest.aforo.ai
// baseUrl: 'https://ingest.aforo.ai',
});
INFO
Store your API key in an environment variable — never hardcode it. There is no tenantId argument: the key already scopes your workspace. customerId is the entity you bill within it.
Call aforo.track() anywhere in your request handler, background job, or webhook processor. The call is non-blocking — it returns immediately and the SDK queues the event for async delivery.
api-handler.ts
import { aforo } from './aforo-client';
export async function handleSearchRequest(req: Request) {
const customerId = req.headers.get('X-Customer-Id')!;
// Your existing business logic — unchanged
const results = await runSearch(req.body.query);
// Record the usage event — non-blocking, async
await aforo.track({
customerId, // the Aforo customer you're billing
metricName: 'api_calls', // a billable unit defined in your dashboard
quantity: 1,
metadata: {
endpoint: '/v1/search',
statusCode: 200,
latencyMs: results.latencyMs,
},
});
return Response.json(results.data);
}
Full Working Example (standalone script)
If you want to test without wiring into your application, pick your language and run this script directly. It fires a single usage event and flushes to confirm delivery before the process exits.
test-track.ts
import { AforoClient } from '@aforo/metering';
const aforo = new AforoClient({ apiKey: 'sk_test_YOUR_KEY_HERE' });
async function main() {
console.log('Firing test usage event...');
await aforo.track({
customerId: 'cust_test_001',
metricName: 'api_calls',
quantity: 1,
metadata: { source: 'quick-start-test' },
});
// shutdown() flushes the buffer and waits for delivery before exit
await aforo.shutdown();
console.log('Event delivered. Check your Aforo dashboard.');
}
main().catch(console.error);
terminal
# Run the test script
npx tsx test-track.ts
# Expected output:
# Firing test usage event...
# Event delivered. Check your Aforo dashboard.
PRO TIP
The SDK buffers events and sends them in batches. Calling await aforo.shutdown() (or flush()) forces immediate delivery — useful in scripts, serverless functions, and test suites where the process exits before the automatic flush interval.
Events appear in the Event Log within 5 seconds of delivery. Rating (converting raw events to dollar amounts based on your rate plan) happens asynchronously and is reflected in the Usage tab within 30 seconds.