@getnotisxyz/sdk
v0.9.1
Published
SDK for Notis. 3 lines to connect your AI agent to your phone.
Maintainers
Readme
@getnotisxyz/sdk
The official SDK for Notis — the agent-to-human communication channel.
Let your AI agents send push notifications to your phone, receive replies, and maintain conversations. Zero dependencies. TypeScript-first.
Install
npm install @getnotisxyz/sdkQuick Start
import { Notis } from '@getnotisxyz/sdk';
const notis = new Notis(); // reads NOTIS_API_KEY from env
await notis.send("I'm alive"); // push notification on your phoneDon't have an API key yet? Run npx @getnotisxyz/cli login then npx @getnotisxyz/cli init to create an agent and save a key to .env automatically.
Getting Your API Key
Recommended (CLI):
npx @getnotisxyz/cli login # authenticate via browser
npx @getnotisxyz/cli init # name your agent, key saved to .envManual (mobile app):
- Download the Notis app
- Create an agent channel
- Copy the API key (shown once)
API
new Notis(config?)
// Zero-config — reads NOTIS_API_KEY from env
const notis = new Notis();
// Explicit config
const notis = new Notis({
apiKey: 'png_live_...', // your API key
baseUrl: 'https://www.getnotis.xyz', // optional
});notis.send(body) — Send a message
// String shorthand
await notis.send("ETH broke $4,000");
// With options
await notis.send("ETH broke $4,000", { priority: 'urgent' });
// Full object form
await notis.send({
title: 'Trade Alert',
body: 'ETH broke $4,000. Want to take profit?',
priority: 'high',
actions: [
{ id: 'sell', label: 'Sell 50%' },
{ id: 'hold', label: 'Hold' },
],
});Priority levels:
| Name | Value | Behavior |
|------|-------|----------|
| lowest | -2 | Silently delivered |
| low | -1 | Quiet delivery |
| normal | 0 | Standard push notification |
| high | 1 | Prominent notification |
| urgent | 2 | Bypasses quiet hours |
notis.listen(handler) — Listen for human messages (Realtime)
Subscribes via Supabase Realtime WebSocket. Messages arrive in <100ms. Auto-falls back to polling if Realtime is unavailable.
Requires @supabase/supabase-js as a peer dependency:
npm install @supabase/supabase-jsconst stop = await notis.listen(async (message, recentHistory) => {
console.log(message.body); // "What's the portfolio looking like?"
// recentHistory = last 10 messages (both directions)
for (const turn of recentHistory) {
console.log(`[${turn.role}] ${turn.body}`);
}
});
stop(); // disconnectOptions:
await notis.listen(handler, {
fallbackToPoll: true, // fall back to polling on failure (default: true)
pollIntervalMs: 5000, // polling interval if falling back (default: 5000)
onError: (err) => {}, // called on Realtime errors
});notis.onMessage(handler) — Listen for human messages (polling)
Deprecated. Use
listen()for instant delivery.onMessage()still works for environments where WebSockets are blocked.
const stop = notis.onMessage(async (message, recentHistory) => {
console.log(message.body);
}, 5000); // poll every 5s
stop(); // stop pollingnotis.onReply(handler) — Listen for action button taps
const stop = notis.onReply(async (reply) => {
console.log(reply.action); // 'sell' | 'hold' | null
console.log(reply.reply_text); // free-text reply or null
}, 5000);
stop();notis.context() — Get user preferences
const ctx = await notis.context();
console.log(ctx.channel); // Channel name
console.log(ctx.preferences); // "Alert me on markets closing within 2 hours"
console.log(ctx.timezone); // "America/Los_Angeles"
console.log(ctx.threshold); // Minimum priority level
console.log(ctx.quiet_hours); // { start: "22:00", end: "08:00" }notis.getHistory(options?) — Load conversation history
const history = await notis.getHistory({ limit: 100 });
for (const msg of history.messages) {
const who = msg.direction === 'agent_to_human' ? 'Agent' : 'Human';
console.log(`[${who}] ${msg.body}`);
}Memory — remember(), recall(), forget()
// Store persistent memory (max 32KB, survives restarts)
await notis.remember({
summary: 'User prefers conservative trades',
preferences: { risk: 'low' },
});
// Read memory
const memory = await notis.recall();
// Clear memory
await notis.forget();notis.ping() — Health check
const alive = await notis.ping(); // true if API key is validTwo-Way Agent Example
import { Notis } from '@getnotisxyz/sdk';
import Anthropic from '@anthropic-ai/sdk';
const notis = new Notis();
const claude = new Anthropic();
await notis.listen(async (msg, recentHistory) => {
const messages = recentHistory.map((turn) => ({
role: turn.role === 'agent' ? 'assistant' as const : 'user' as const,
content: turn.body,
}));
const response = await claude.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 1024,
system: 'You are a helpful trading assistant.',
messages,
});
const reply = response.content[0].type === 'text'
? response.content[0].text : 'Done.';
await notis.send(reply);
});
console.log('Agent is listening...');REST API (No SDK)
# Send a message
curl -X POST https://www.getnotis.xyz/api/notify \
-H "Authorization: Bearer png_live_..." \
-H "Content-Type: application/json" \
-d '{"body": "Something happened", "priority": 1}'
# Poll for human messages
curl https://www.getnotis.xyz/api/inbox \
-H "Authorization: Bearer png_live_..."
# Get user context
curl https://www.getnotis.xyz/api/context \
-H "Authorization: Bearer png_live_..."Upgrading from v0.5
The Ping and PingClient class names still work — no breaking changes:
// Old (still works)
import { Ping } from '@getnotisxyz/sdk';
const ping = new Ping({ apiKey: '...' });
// New (recommended)
import { Notis } from '@getnotisxyz/sdk';
const notis = new Notis(); // reads from envMethod renames (old names still work):
getContext()→context()getMemory()→recall()setMemory()→remember()clearMemory()→forget()
Error Handling
import { Notis, NotisError } from '@getnotisxyz/sdk';
try {
await notis.send('Test');
} catch (err) {
if (err instanceof NotisError) {
console.error(err.message); // Human-readable error
console.error(err.status); // HTTP status code
}
}License
MIT
