Hushpiper Download

Developers

Build bots for Hushpiper.

A small API for bots that join chats and answer: a quiz for a book club, order updates from a shop, a team's morning stand-up. A bot reads only what people send to it, and everyone in the chat can see it's there.

At a glance

A bot, in four parts

A bot is an account your code runs. People add it to a chat or message it directly, and it answers.

Create

Make a bot in the developer console. It gets a name, a picture and a username ending in _bot.

Receive

Messages sent to your bot reach your server as signed webhooks, or ask for them with GET /updates.

Reply

One call sends text, buttons or a photo back to the chat. Editing and deleting work the same way.

Stay private

Messages to a bot are sealed for that bot alone. Everything else in the chat stays end-to-end encrypted between people.

Getting started

Three steps to a first reply

Keys are handed out by a person, not a sign-up form.

1

Ask for a key

Tell us what your bot will do and who it's for (see Onboarding). We set up your account with you.

2

Create a bot

In the console you get an API key (hp_live_…) and the bot's own encryption key, which stays on your server.

3

Listen and reply

Set your webhook address, then answer each message with one call. Our bot library (Node.js and Python first) seals and opens messages for you.

# Every call sends your key. Who am I?
curl https://hushpiper.com/api/bot/v1/me \
  -H "Authorization: Bearer hp_live_…"

# 200 OK
{ "id": "b_7Hq2", "username": "bookclub_bot", "name": "Book Club Quiz", "state": "live" }

Endpoints

Small on purpose

Everything a bot does, in ten routes. There is no route that reads a chat's history or lists people who didn't talk to the bot.

MethodRouteWhat it does
GET/meThe bot's name, username, picture and state.
PATCH/meChange its name, picture, description and the commands it lists.
PUT/webhookWhere updates are sent, and the secret they're signed with.
GET/updates?after=…New messages and events, for a bot that asks instead of taking webhooks.
GET/chats/{chat}The chat's name and what its admins let the bot do there.
GET/chats/{chat}/keysThe public keys a reply is sealed with. No names, nothing else.
POST/chats/{chat}/messagesSend a message: text, buttons, a photo or a file.
PATCH/chats/{chat}/messages/{id}Edit a message the bot sent.
DELETE/chats/{chat}/messages/{id}Delete a message the bot sent.
POST/chats/{chat}/leaveLeave a chat.
HOOKmessage, button, added, removedWhat your webhook receives.

Every route starts https://hushpiper.com/api/bot/v1. Answers are JSON; times are UTC, like 2026-09-26T14:02:11Z.

The flow

Message in, reply out

Someone writes to the bot, your server hears about it, the bot answers. Our server passes on sealed envelopes and never sees the words.

1. Someone writes to the bot

In a direct chat, or in a group with a command like /quiz, a mention of the bot, or a reply to it. Your webhook gets:

POST https://your-server.example/hushpiper
X-Hushpiper-Signature: t=1790431200,v1=5f2c9e…

{
  "update_id": 1042,
  "type": "message",
  "chat": { "id": "c_8Fq2", "type": "group", "title": "Book club" },
  "from": { "username": "maya" },
  "message": { "id": "m_91kD", "sealed": "hp1.AAAB…" }
}

2. Your bot opens it

Only the bot's own key opens sealed. The library checks the signature and opens it in one line:

const msg = await bot.open(request);   // { text: "/quiz", from: "maya", chat: "c_8Fq2" }

3. The bot answers

The library seals the reply for the people in the chat and sends it. Send the same Idempotency-Key again and nothing is sent twice.

await bot.reply(msg, 'Question 1: who wrote Middlemarch?', {
  buttons: [['George Eliot', 'Jane Austen'], ['Charlotte Brontë']],
});

# What it sends
POST /api/bot/v1/chats/c_8Fq2/messages
Idempotency-Key: 6f1d2c9a-41be-4c1e-9f0a-2d7c55e0b3a1
{ "sealed": "hp1.AAAC…", "reply_to": "m_91kD" }

# 201 Created
{ "id": "m_91kE", "sent_at": "2026-09-26T14:02:11Z" }

Bot states

Where a bot is in its life

The same states you see in the console, and in GET /me.

draft
Just made. Only you can talk to it, in a direct chat.
in_review
You asked for it to be listed where people can find it. A person is checking it against our guidelines.
live
People can find it, message it and add it to their chats.
paused
You paused it. It stays in its chats, says it's paused, and gets no messages.
suspended
We stopped it, usually after reports. You're told why, and you can appeal.

Privacy

What a bot can and can't see

Hushpiper stays end-to-end encrypted for people. A bot is let in only to the messages meant for it.

A bot can see

  • Messages sent to it: everything in a direct chat with it; in a group, only commands (/quiz), mentions of it and replies to it.
  • The username of whoever wrote to it.
  • The chat's name, and what the chat's admins let it do.

A bot can't see

  • Any other message in the chat. Those stay sealed between people's devices.
  • Phone numbers, email addresses, online status, last seen or read receipts.
  • Who else is in the chat, unless the chat shows its members to everyone.
  • Anyone who hasn't messaged it or added it: a bot can't start a chat.
Book Club Quiz is a bot. It reads only messages sent to it.

That line shows in the chat when a bot joins, and on the bot's profile. Group admins decide which bots join, and can remove one at any time.

Errors, limits

What a refusal looks like

Every error has a stable code for your program and a plain message for your logs.

StatusCodeWhat it means
400bad_requestNot valid JSON, or a field is missing.
401unauthorizedNo key, or a key that was revoked.
403not_allowed_hereThe bot isn't in that chat, or its admins don't allow that.
404not_foundNo such chat or message, or not one the bot can see.
409idempotency_conflictThat Idempotency-Key was used with a different request.
422invalidA field is wrong. The message says which.
429rate_limitedToo fast. Retry-After says when to try again.
# 403 Forbidden
{
  "error": {
    "code": "not_allowed_here",
    "message": "The admins of this chat don't let bots send photos."
  }
}

Limits

Up to 30 messages a second across all chats, and 20 a minute in any one group. Over that, you get a 429.

Idempotency

Send an Idempotency-Key with every POST. The same key within 24 hours returns the first answer instead of sending twice.

Signed webhooks

X-Hushpiper-Signature is an HMAC-SHA256 of the time and the body, with your webhook secret. Refuse anything older than 5 minutes. Failed deliveries are retried for 24 hours.

Onboarding

Talk to us for a key

The Bot API opens to a few partners first. Write to us with:

  • what your bot will do, and who it's for;
  • roughly how many chats you expect;
  • what you need first: webhooks, buttons, files or payments.
Email hello@hushpiper.com Open the developer console

The console signs in with your Hushpiper account.

Hushpiper is new. Found something wrong?Report a problem

Goes only to the Hushpiper team, with this page's address and your screen size. Don't include passwords or recovery words.