NxCreateDocs

API Reference

Complete reference for the NxCreator public API — API key authentication, bot management, and custom webhooks.

The NxCreator public API uses a personal API key for authentication. All endpoints live under the same base URL and accept JSON.

Base URL
https://api-prod-nexcreate-01.nx3r.com

Authentication

Pass your API key as apiKey in the JSON body (POST) or query string (GET). The authenticated user is resolved from the key — no separate uid needed.

An invalid or missing key returns 401 Invalid API Key.

Getting your API key

Your API key is available in the NxCreator dashboard. Open Settings, scroll to the API Key section, and click Copy. The key is generated automatically on first visit and remains stable until you regenerate it.

Treat your API key like a password. It grants full access to your bots and account. Never expose it in client-side code or public repositories.

apiv3 — Bot management

The /apiv3/:path route accepts both GET and POST. Pass apiKey in the body (POST) or query string (GET). The authenticated user is resolved from the key — no separate uid needed.

restartBot

POST /apiv3/restartBot
{ "apiKey": "...", "botId": "abc123" }
{ "ok": true, "msg": "Bot restarted", "stat_code": 200 }

transferBot

Copies the bot and its code to another NxCreator account. Optionally starts the bot immediately on the new account if run_now is true (requires newBotToken). You can also seed initial data into the new bot's collections using dbProps.

FieldTypeRequiredDescription
apiKeystringYesYour API key.
botIdstringYesID of the bot to transfer.
targetEmailstringYesEmail of the recipient NxCreator account.
newBotTokenstringNoBot token for the new bot on the recipient account.
run_nowbooleanNoStart the new bot immediately. Requires `newBotToken`.
dbPropsobjectNoInitial collection data to seed into the new bot. Keys are collection names (no underscores), values are arrays of documents.
POST /apiv3/transferBot
{
  "apiKey": "...",
  "botId": "abc123",
  "targetEmail": "[email protected]",
  "newBotToken": "123:AAA...",
  "run_now": true,
  "dbProps": {
    "settings": [{ "key": "welcomeMsg", "value": "Hello!" }],
    "admins":   [{ "userId": 9876543, "role": "owner" }]
  }
}
{
  "ok": true,
  "msg": "Bot transferred",
  "stat_code": 200,
  "newBotId": "def456",
  "dbProps": {
    "settings": { "inserted": 1 },
    "admins":   { "inserted": 1 }
  }
}
Collection names in dbProps must not contain underscores and follow the same rules as regular bot collection names. Each document array is seeded into the corresponding collection on the new bot. Errors per collection are reported individually without blocking the rest of the transfer.

editBotCoreLogic

Overwrites the full bot code file. The bot must be restarted separately for changes to take effect.

POST /apiv3/editBotCoreLogic
{ "apiKey": "...", "botId": "abc123", "newCode": "bot.command('start', ctx => ctx.reply('Hi'));" }
{ "ok": true, "msg": "Code updated", "stat_code": 200 }

getbotCode

POST /apiv3/getbotCode
{ "apiKey": "...", "botId": "abc123" }
{ "ok": true, "msg": "Code fetched", "stat_code": 200, "data": "// bot code..." }

Broadcast API

The Broadcast API lets you send a message to all your bot's users in one call. Jobs run at 30–40 messages per second with automatic 429 back-off. Each bot can have at most one active broadcast at a time — new jobs queue automatically behind the running one.

Broadcast base URL
https://api-prod-nexcreate-01.nx3r.com

Auth header
X-Bot-Token: <your bot token>

POST /broadcast — queue a job

FieldTypeRequiredDescription
botIdstringYesYour bot ID.
typestringNoMessage type. One of: text, photo, video, audio, document, animation, voice, video_note, sticker, location, contact, poll. Defaults to text.
textstringtext typeMessage body. Required when type=text.
mediastringmedia typesfile_id or public URL. Required for photo/video/audio/document/animation/voice/video_note/sticker.
captionstringNoCaption for photo/video/audio/document/animation/voice.
parseModestringNoHTML, Markdown, or MarkdownV2.
buttonsarrayNoUp to 2 inline URL buttons. Each item: { text, url }.
extraobjectNoAny extra Telegram API params (merged last, after buttons).
filterobjectNoScope broadcast: { lang: "en" } sends only to users with that language.
# Plain text broadcast
curl -X POST https://api-prod-nexcreate-01.nx3r.com/broadcast \
  -H "X-Bot-Token: <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "botId": "abc123",
    "type": "text",
    "text": "Hey! We just launched something new 🚀",
    "parseMode": "HTML",
    "buttons": [
      { "text": "Check it out", "url": "https://example.com/launch" },
      { "text": "Read the blog", "url": "https://example.com/blog" }
    ]
  }'
{ "ok": true, "jobId": "a1b2c3d4e5f6a7b8", "status": "queued" }

You can attach up to 2 inline URL buttons via the buttons field. Each button requires a text label and an url (must start with http:// or https://). The buttons appear in a single row below the message.

# Photo broadcast with one button
curl -X POST https://api-prod-nexcreate-01.nx3r.com/broadcast \
  -H "X-Bot-Token: <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "botId": "abc123",
    "type": "photo",
    "media": "AgACAgIAAxk...",
    "caption": "New feature dropped!",
    "parseMode": "HTML",
    "buttons": [{ "text": "Open app", "url": "https://t.me/your_bot/app" }]
  }'

GET /broadcast/:jobId — check status

curl "https://api-prod-nexcreate-01.nx3r.com/broadcast/a1b2c3d4e5f6a7b8?botId=abc123" \
  -H "X-Bot-Token: <token>"
{
  "ok": true,
  "job": {
    "jobId": "a1b2c3d4e5f6a7b8",
    "status": "running",
    "total": 12400,
    "sent": 4210,
    "failed": 38
  }
}

DELETE /broadcast/:jobId — cancel

curl -X DELETE https://api-prod-nexcreate-01.nx3r.com/broadcast/a1b2c3d4e5f6a7b8 \
  -H "X-Bot-Token: <token>" \
  -H "Content-Type: application/json" \
  -d '{ "botId": "abc123" }'
Cancellation is near-instant — the loop stops within one send cycle (~33 ms). Messages already sent are not recalled.

GET /jobs/:botId — recent jobs

Returns the last 20 broadcast jobs for a bot. Running jobs show live progress.

curl "https://api-prod-nexcreate-01.nx3r.com/jobs/abc123" \
  -H "X-Bot-Token: <token>"

Custom Webhooks

Every bot can expose HTTP endpoints you define directly in bot code. No API key is required to call them — auth is up to you inside the handler.

Webhook base URL
https://api-prod2-next-bot.nx3r.com

Route pattern (all HTTP methods accepted)
/custom/:botId/:customPath

Webhook handler contract

Assign an async function to logic['yourPath'] in your bot code:

logic['notify'] = async (query, body, db, response, params) => {
  const userId = body.userId;
  if (!userId) {
    response.statusCode = 400;
    response.message = 'userId is required';
    return;
  }
  const user = await db.operation.findOne('users', { userId });
  await bot.telegram.sendMessage(userId, `Hello ${user?.name ?? 'there'}!`);
  response.statusCode = 200;
  response.data = { sent: true };
};
curl -X POST "https://api-prod2-next-bot.nx3r.com/custom/<botId>/notify" \
  -H "Content-Type: application/json" \
  -d '{"userId": 9876543}'

Response object

Mutate the response object inside your handler to control the HTTP response:

FieldTypeDescription
statusCodenumberHTTP status code. Defaults to 200. The top-level `ok` field is `true` when < 400.
headersobjectExtra response headers (e.g. `{ "X-Request-Id": "abc" }`).
messagestringShort human-readable message included in the JSON body.
dataanyPayload returned under the `data` key. If unset and the handler returns a value, that return value is used automatically.
HTTP statusCause
400Invalid path format, or no `logic` handler registered for the requested path.
403Bot is under halt — restart it from the dashboard to resume.
404Bot ID not found.
500Compile or runtime error inside the handler. Full details appear in the bot error log.

Common use cases

Custom webhooks let any external service trigger bot actions over HTTP. Because they run inside the full bot runtime, you have access to bot.telegram, the db helper, and axios — everything your normal bot code can use.

Push notifications from an external service

Trigger a Telegram message to a user from a payment gateway, CI pipeline, or any backend event.

logic['notify'] = async (query, body, db, response) => {
  const { userId, text } = body;
  if (!userId || !text) { response.statusCode = 400; response.message = 'userId and text required'; return; }
  await bot.telegram.sendMessage(userId, text);
  response.data = { sent: true };
};

Broadcast a message to all bot users

logic['broadcast'] = async (query, body, db, response) => {
  const { text } = body;
  if (!text) { response.statusCode = 400; response.message = 'text required'; return; }
  const users = await db.operation.findAll('users', {});
  let sent = 0;
  for (const u of users) {
    try { await bot.telegram.sendMessage(u.userId, text); sent++; } catch {}
  }
  response.data = { sent, total: users.length };
};

Receive third-party webhooks

Use a custom webhook as the callback URL for Stripe, GitHub, or any other service. Validate the payload and store or act on it inside the handler.

logic['stripe-event'] = async (query, body, db, response) => {
  if (body.type === 'checkout.session.completed') {
    const userId = Number(body.data?.object?.metadata?.telegramUserId);
    if (userId) {
      await db.operation.setProp('users', { userId }, 'isPremium', true);
      await bot.telegram.sendMessage(userId, 'Payment confirmed — you are now premium!');
    }
  }
  response.data = { received: true };
};

Expose bot data as a mini API

Read from your bot's collections and return JSON — useful for a companion web app or dashboard.

logic['stats'] = async (query, body, db, response) => {
  const total = await db.operation.countDocuments('users', {});
  const premium = await db.operation.countDocuments('users', { isPremium: true });
  response.data = { total, premium };
};

Simple token-based auth

Custom webhook routes have no built-in auth. Add your own secret check at the top of any handler that should be private.

const SECRET = 'my-secret-token';

logic['admin-action'] = async (query, body, db, response) => {
  if (query.token !== SECRET) {
    response.statusCode = 401;
    response.message = 'Unauthorized';
    return;
  }
  // safe to proceed
  response.data = { ok: true };
};
Store your webhook secret in the bot's env vars and read it with process.env.MY_SECRET instead of hardcoding it.
Last updated August 11, 2026
Was this page helpful?