Tailpoint SDK
Small Node SDK for sending ingestion events to the Tailpoint backend.
Install
npm install @peegee/tailpoint-sdk
Consumers do not need a custom .npmrc entry or package-registry login to install the public package.
Initialize
import { init } from '@peegee/tailpoint-sdk';
init({
apiKey: process.env.TAILPOINT_INGESTION_KEY!,
endpoint: 'https://api.tailpoint.com/api',
source: 'sdk',
});
The endpoint should be the backend API base that already includes /api, so the SDK can post to v1/ingest/tasks underneath it.
source defaults to sdk if you omit it. Pass it explicitly only when you want a different ingestion source such as api, sentry, or manual.
Live Keys vs Test Keys
trk_live_...keys create or dedupe tasks in the target project.- If a matching live event hits a previously closed task, the backend may reopen that task depending on the project's closed-task dedupe setting.
trk_test_...keys validate payloads and key/project wiring without creating tasks.
The backend currently returns:
201 { status: "created", taskId, occurrenceCount }200 { status: "deduped", taskId, occurrenceCount }200 { status: "validated", test: true }
Direct Capture
import { capture, init } from '@peegee/tailpoint-sdk';
init({
apiKey: process.env.TAILPOINT_INGESTION_KEY!,
endpoint: 'https://api.tailpoint.com/api',
source: 'sdk',
});
await capture({
title: 'Nightly sync failed',
description: 'The sync worker exited with code 1.',
severity: 'high',
priority: 1,
metadata: {
service: 'sync-worker',
env: process.env.NODE_ENV,
},
dedupeKey: 'sync-worker:nightly-failure',
});
severity and priority are separate fields:
severitycontrols ingestion-level triageprioritymaps to the created task's workflow priority
Use a stable dedupeKey for repeated failures you want grouped into the same task.
Capture Errors
import { captureError, init } from '@peegee/tailpoint-sdk';
init({
apiKey: process.env.TAILPOINT_INGESTION_KEY!,
endpoint: 'https://api.tailpoint.com/api',
source: 'sdk',
});
try {
await runJob();
} catch (error) {
await captureError(error, {
severity: 'critical',
metadata: {
job: 'billing-rollup',
},
});
}
If you do not pass a dedupeKey, the SDK derives one from the error message and top stack frame.
Express Middleware Example
import express from 'express';
import { errorHandler, init } from '@peegee/tailpoint-sdk';
init({
apiKey: process.env.TAILPOINT_INGESTION_KEY!,
endpoint: 'https://api.tailpoint.com/api',
source: 'sdk',
});
const app = express();
app.get('/boom', () => {
throw new Error('Example route crash');
});
app.use(
errorHandler({
severity: 'high',
metadata: { app: 'api-gateway' },
}),
);
Fastify Example
import Fastify from 'fastify';
import { captureError, init } from '@peegee/tailpoint-sdk';
init({
apiKey: process.env.TAILPOINT_INGESTION_KEY!,
endpoint: 'https://api.tailpoint.com/api',
source: 'sdk',
});
const app = Fastify();
app.setErrorHandler((error, _request, reply) => {
void captureError(error, {
severity: 'high',
metadata: { app: 'api-gateway' },
});
reply.status(500).send({ ok: false });
});
Global Crash Behavior
You can opt into automatic capture for unhandled promise rejections and uncaught exceptions:
init({
apiKey: process.env.TAILPOINT_INGESTION_KEY!,
endpoint: 'https://api.tailpoint.com/api',
source: 'sdk',
captureUnhandledRejections: true,
captureUncaughtExceptions: true,
});
Important notes:
- The SDK captures the crash event, but it does not swallow the original failure.
- Your process manager should still restart the service after fatal crashes.
- If ingestion fails, the SDK forwards that failure to the optional
onErrorcallback.
Rate Limits
The ingestion API is rate limited per ingestion key.
If you receive 429 Too Many Requests:
- treat it as a temporary failure
- back off and retry after the cooldown window
- honor
Retry-Afterif your HTTP client exposes it
Common Setup Mistakes
- Using an endpoint that does not include
/api - Exposing the ingestion key in browser code or public env vars
- Using a changing
dedupeKeysuch as one that includes timestamps - Expecting a test key to create tasks