Backprompter

Backprompter Server SDK

Call Backprompter agents from a Node.js backend with a server API key. Use this when your own backend talks to Backprompter on behalf of your users.

Overview

The SDK authenticates with an API key and never needs a browser session. It covers agent calls, end-user data, and identity tokens for your own login.

Keep the API key on your server An API key carries full access to the app it belongs to. Never ship it in browser code. To give a browser access, mint a per-user token with createUserToken.
Calling from a browser? For web apps, use the Backprompter Browser SDK instead.

Get your keys

ValueWhere to find it
API key Dashboard, your app, the Deploy modal. It looks like bp_live_xxxxx.<secret>. Keep it server-side only.
App Key Your app and tenant id, from the same Deploy modal.

Install

npm install backprompter-server-sdk

This requires Node.js 18 or later, because it uses the built-in fetch.

Quick start

import BackprompterServer from 'backprompter-server-sdk';

const bp = new BackprompterServer({
  apiKey: process.env.BACKPROMPTER_API_KEY,   // bp_live_xxxxx.<secret>
  tenantId: process.env.BACKPROMPTER_APP_KEY, // your App Key
});

const result = await bp.run({
  agentId: 'your-agent-name',        // or omit to auto-route
  userPrompt: 'Summarize this support ticket.',
  conversationHistory: [],
  profileString: 'Enterprise customer',
});

console.log(result.response);   // the agent's reply
// result.agentId, result.artifactType

Run an agent

const result = await bp.run({
  userPrompt: 'What changed last quarter?',
  // agentId: 'analyst',      // omit to auto-route to the best agent
  conversationHistory: [],    // array of { role, content } pairs
  profileString: '',          // optional user-profile context
  // fileInputs: [],          // attachments, see below
  // urlInputs: [],           // URLs to attach as context
  // contextLimit: 120000,    // characters of history before auto-summarization
  // maxTokens: 1000,
  // ragCharBudget: 20000,
  // tenantId: 'other-app',   // overrides the constructor value for this call
});

Attachments

Inside fileInputs, the key you use decides how the attachment is sent.

KeySent as
url, dataUrl, base64image
file_url, file_datadocument

Backprompter infers the real type wherever it can. It reads an explicit mimeType, the data-URL prefix, the file extension, or the leading bytes of base64. It falls back to the key only when the type cannot be determined.

await bp.run({
  agentId: 'analyst',
  userPrompt: 'What are the Q3 totals?',
  fileInputs: [
    { file_url: 'https://example.com/q3.pdf', filename: 'q3.pdf' },  // document
    { url: 'https://example.com/chart.png' },                        // image
  ],
});

Document support varies by model. OpenAI models accept spreadsheets. Anthropic models accept PDF only, and they reject other types outright. Choose a model that handles what you send.

Keep your own login

Your app can keep its own login. Backprompter never has to see a password. Your backend exchanges your user id for a session token, and your frontend signs in with that token. The frontend then reaches every Browser SDK function, including saveData, search, file handling, and voice.

// your backend, behind your own session check
app.post('/api/bp-token', requireMyAuth, async (req, res) => {
  const { customToken } = await bp.createUserToken({
    externalId: req.user.id,        // your own user id
    email: req.user.email           // a label for your dashboard
  });
  res.json({ customToken });
});
// your frontend, after your own login succeeds
const { customToken } = await fetch('/api/bp-token').then((r) => r.json());
await Backprompter.signInWithCustomToken(customToken);

Backprompter derives a storage id from your tenant id and your external id. The same external id always returns to the same data. You cannot choose the id.

Keep the API key on your server. Only the token reaches the browser. A token is valid for one user of one app.

End-user data from your backend

You can also skip the browser session and do everything from your server. Call forUser() with your own user id.

const user = bp.forUser('u_8821');

await user.saveData('preferences', { theme: 'dark' });
const prefs = await user.getData('preferences');
await user.deleteData('preferences');

await user.saveConversation(conversationId, messages, { title: 'Support' });
const list = await user.listConversations();
const convo = await user.getConversation(conversationId);
await user.deleteConversation(conversationId);

await user.storeArtifacts([{ name: 'notes.md', content: text }]);
const arts = await user.listArtifacts();
const hits = await user.search('last quarter revenue', { k: 5 });

const ent = await user.getEntitlements();
const { url } = await user.createCheckoutSession({ successUrl, cancelUrl });

Every call reads and writes that person's data only. The API key decides the app. The external id decides the person.

Agent calls are not user-scoped The handle covers stored data. Keep agent calls on bp.run(), and pass what the agent should know about the person in profileString.
const profile = await user.getData('profile');
const result = await bp.run({
  agentId: 'analyst',
  userPrompt: 'What changed?',
  profileString: JSON.stringify(profile.data)
});

API key scopes

New API keys carry three scopes.

ScopeAllows
run:publicbp.run()
enduser:databp.forUser(...)
identity:exchangebp.createUserToken(...)

Keys generated before these features existed carry run:public only. To use forUser() or createUserToken(), generate a new key from the Deploy modal.

A key reaches only the app it was made for. A request naming another app returns 403, even when the same developer owns both.

Payments

An API key never triggers the Backprompter payment gate. Your backend is your own integration, so you decide what a person may do.

Read the entitlement yourself when you want to enforce payment.

const { active, paymentRequired } = await bp.forUser('u_8821').getEntitlements();
if (paymentRequired && !active) {
  return res.status(402).json({ error: 'Subscribe first' });
}

The gate applies only to end users signed in with a Backprompter token. That includes users who signed in with a custom token from createUserToken().

If you collect money outside Backprompter, leave the Backprompter payment settings empty. No gate then applies to anyone.

Notes and limits