@nope-net/sdk
v1.1.0
Published
TypeScript SDK for the NOPE safety API - risk classification for conversations
Downloads
303
Maintainers
Readme
NOPE Node SDK
TypeScript SDK for the NOPE safety API - risk classification for conversations.
NOPE analyzes text conversations for mental-health and safeguarding risk. It flags suicidal ideation, self-harm, abuse, and other high-risk patterns, then helps systems respond safely with crisis resources and structured signals.
Requirements
- Node.js 18 or higher (uses native
fetch) - A NOPE API key (get one here)
Installation
npm install @nope-net/sdk
# or
pnpm add @nope-net/sdk
# or
yarn add @nope-net/sdkQuick Start
import { NopeClient } from '@nope-net/sdk';
// Get your API key from https://dashboard.nope.net
const client = new NopeClient({ apiKey: 'nope_live_...' });
const result = await client.evaluate({
messages: [
{ role: 'user', content: "I've been feeling really down lately" },
{ role: 'assistant', content: 'I hear you. Can you tell me more?' },
{ role: 'user', content: "I just don't see the point anymore" }
],
config: { user_country: 'US' }
});
console.log(`Severity: ${result.summary.speaker_severity}`); // e.g., "moderate", "high"
console.log(`Imminence: ${result.summary.speaker_imminence}`); // e.g., "subacute", "urgent"
// Access crisis resources
for (const resource of result.crisis_resources) {
console.log(` ${resource.name}: ${resource.phone}`);
}Crisis Screening (SB243 Compliance)
For lightweight suicide/self-harm screening that satisfies California SB243, NY Article 47, and similar regulations:
const result = await client.screen({
text: "I've been having dark thoughts lately"
});
if (result.show_resources) {
console.log(`Suicidal ideation: ${result.suicidal_ideation}`);
console.log(`Self-harm: ${result.self_harm}`);
console.log(`Rationale: ${result.rationale}`);
if (result.resources) {
console.log(`Call ${result.resources.primary.phone}`);
}
}The /v1/screen endpoint is ~20x cheaper than /v1/evaluate and returns independent detection flags (suicidal_ideation, self_harm), pre-formatted crisis resources, and audit trail fields (request_id, timestamp).
Configuration
const client = new NopeClient({
apiKey: 'nope_live_...', // Required for production
baseUrl: 'https://api.nope.net', // Optional, for self-hosted
timeout: 30000, // Request timeout in milliseconds
});Evaluate Options
const result = await client.evaluate({
messages: [...],
config: {
user_country: 'US', // ISO country code for crisis resources
locale: 'en-US', // Language/region
user_age_band: 'adult', // "adult", "minor", or "unknown"
dry_run: false, // If true, don't log or trigger webhooks
},
userContext: 'User has history of anxiety', // Optional context
});Response Structure
const result = await client.evaluate({ messages: [...], config: { user_country: 'US' } });
// Summary (speaker-focused)
result.summary.speaker_severity // "none", "mild", "moderate", "high", "critical"
result.summary.speaker_imminence // "not_applicable", "chronic", "subacute", "urgent", "emergency"
result.summary.any_third_party_risk // boolean
result.summary.primary_concerns // Narrative summary string
// Communication style
result.communication.styles // [{ style: "direct", confidence: 0.9 }, ...]
result.communication.language // "en"
// Individual risks (subject + type)
for (const risk of result.risks) {
console.log(`${risk.subject} ${risk.type}: ${risk.severity} (${risk.imminence})`);
console.log(` Confidence: ${risk.confidence}, Subject confidence: ${risk.subject_confidence}`);
console.log(` Features: ${risk.features.join(', ')}`);
}
// Crisis resources (matched to user's country)
for (const resource of result.crisis_resources) {
console.log(resource.name);
if (resource.phone) {
console.log(` Phone: ${resource.phone}`);
}
if (resource.text_instructions) {
console.log(` Text: ${resource.text_instructions}`);
}
}
// Recommended reply (if configured)
if (result.recommended_reply) {
console.log(`Suggested response: ${result.recommended_reply.content}`);
}
// Legal/safeguarding flags
if (result.legal_flags?.ipv?.indicated) {
console.log(`IPV detected - lethality: ${result.legal_flags.ipv.lethality_risk}`);
}
if (result.legal_flags?.safeguarding_concern?.indicated) {
console.log(`Safeguarding concern: ${result.legal_flags.safeguarding_concern.context}`);
}Error Handling
import {
NopeClient,
NopeAuthError,
NopeRateLimitError,
NopeValidationError,
NopeServerError,
NopeConnectionError,
} from '@nope-net/sdk';
const client = new NopeClient({ apiKey: 'nope_live_...' });
try {
const result = await client.evaluate({ messages: [...], config: {} });
} catch (error) {
if (error instanceof NopeAuthError) {
console.log('Invalid API key');
} else if (error instanceof NopeRateLimitError) {
console.log(`Rate limited. Retry after ${error.retryAfter}ms`);
} else if (error instanceof NopeValidationError) {
console.log(`Invalid request: ${error.message}`);
} else if (error instanceof NopeServerError) {
console.log('Server error, try again later');
} else if (error instanceof NopeConnectionError) {
console.log('Could not connect to API');
}
}Plain Text Input
For transcripts or session notes without structured messages:
const result = await client.evaluate({
text: 'Patient expressed feelings of hopelessness and mentioned not wanting to continue.',
config: { user_country: 'US' }
});TypeScript Support
This SDK is written in TypeScript and exports all types:
import type {
EvaluateResponse,
Risk,
Summary,
CommunicationAssessment,
CrisisResource,
Severity,
Imminence,
RiskSubject,
RiskType,
} from '@nope-net/sdk';Webhook Verification
If you've configured webhooks in the dashboard, use Webhook.verify() to validate incoming payloads:
import { Webhook, WebhookPayload, WebhookSignatureError } from '@nope-net/sdk';
app.post('/webhooks/nope', (req, res) => {
try {
const event: WebhookPayload = Webhook.verify(
req.body,
req.headers['x-nope-signature'] as string,
req.headers['x-nope-timestamp'] as string,
process.env.NOPE_WEBHOOK_SECRET!
);
console.log(`Received ${event.event}: ${event.risk_summary.overall_severity}`);
// Handle the event
if (event.event === 'risk.critical') {
// Immediate escalation needed
} else if (event.event === 'risk.elevated') {
// Review recommended
}
res.status(200).send('OK');
} catch (err) {
if (err instanceof WebhookSignatureError) {
console.error('Webhook verification failed:', err.message);
res.status(401).send('Invalid signature');
} else {
throw err;
}
}
});Webhook Options
const event = Webhook.verify(
payload,
signature,
timestamp,
secret,
{
maxAgeSeconds: 300, // Default: 5 minutes. Set to 0 to disable timestamp checking.
}
);Testing Webhooks
Use Webhook.sign() to generate test signatures:
const payload = { event: 'test.ping', /* ... */ };
const { signature, timestamp } = Webhook.sign(payload, secret);
// Use in test requests
await fetch('/webhooks/nope', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-NOPE-Signature': signature,
'X-NOPE-Timestamp': timestamp,
},
body: JSON.stringify(payload),
});Risk Taxonomy
NOPE uses an orthogonal taxonomy separating WHO is at risk from WHAT type of harm:
Subjects (who is at risk)
| Subject | Description |
|---------|-------------|
| self | The speaker is at risk |
| other | Someone else is at risk (friend, family, stranger) |
| unknown | Ambiguous - "asking for a friend" territory |
Risk Types (what type of harm)
| Type | Description |
|------|-------------|
| suicide | Self-directed lethal intent |
| self_harm | Non-suicidal self-injury (NSSI) |
| self_neglect | Severe self-care failure |
| violence | Harm directed at others |
| abuse | Physical, emotional, sexual, financial abuse |
| sexual_violence | Rape, sexual assault, coerced acts |
| neglect | Failure to provide care for dependents |
| exploitation | Trafficking, forced labor, sextortion |
| stalking | Persistent unwanted contact/surveillance |
Severity & Imminence
Severity (how serious):
| Level | Description |
|-------|-------------|
| none | No concern |
| mild | Low-level concern |
| moderate | Significant concern |
| high | Serious concern |
| critical | Extreme concern |
Imminence (how soon):
| Level | Description |
|-------|-------------|
| not_applicable | No time-based concern |
| chronic | Ongoing, long-term |
| subacute | Days to weeks |
| urgent | Hours to days |
| emergency | Immediate |
API Reference
For full API documentation, see docs.nope.net.
Versioning
This SDK follows Semantic Versioning. While in 0.x.x, breaking changes may occur in minor versions.
Changelog
See CHANGELOG.md for release history.
License
MIT - see LICENSE for details.
Support
- Documentation: docs.nope.net
- Dashboard: dashboard.nope.net
- Issues: github.com/nope-net/node-sdk/issues
