Skip to main content

BuddyPro End-user API (Client API)

OpenAI-compatible API access for BuddyPro end-users — any Buddy user can generate their own key to programmatically access their personal BuddyPro profile. This is a pay-per-use API billed via prepaid credits purchased through the BuddyPro instance you use; the instance sets the per-request price. It accepts requests structured like the OpenAI Chat Completions API and returns responses in the same format, with BuddyPro-specific extensions in message (e.g., image, audio).

Not the Owner API. If you are a BuddyPro instance owner or team member building internal tools, automations, or service integrations, see the Owner API (separate B2B documentation) instead.

Overview

PropertyValue
PathPOST /v1/chat/completions
AuthAuthorization: Bearer bapi_B2C_... header
FormatOpenAI Chat Completions compatible
BillingPrepaid credits (Stripe) — purchased through your BuddyPro instance, billed per request
StreamingNot supported yet

Who Can Use the Client API

Any authenticated BuddyPro user can generate a Client API key — not just instance owners or team members — provided the instance owner has enabled the Client API. The Client API is off by default; if the owner hasn't turned it on, /generateClientApiKey returns an error and existing keys stop working. Once enabled, the key is tied to your own personal BuddyPro profile: every request is processed as if you sent a message in Telegram, with full access to your conversation history, long-term memory, and personal settings.

To actually use the key, you must set up credit billing — and that has two requirements:

  • An active subscription to the BuddyPro instance you are using.
  • The instance must accept API credit payments. Billing is handled by the instance (its owner), who sets the per-request price; an instance whose owner hasn't enabled API payments cannot sell you credits.

If either requirement isn't met, /setupApiCredits returns an explanatory error (see Setting Up Credit Billing).

Persistent Memory & Conversation History

Like the Telegram interface, BuddyPro maintains long-term memory and full conversation history for your profile. Every API request is treated exactly like a message sent in Telegram — it is saved to your chat history, contributes to BuddyPro's memory about you, and influences future responses.

This means:

  • Conversations are cumulative. BuddyPro remembers everything said through the API, just as it remembers Telegram conversations. You do not need to (and should not) send conversation history — just send the current message.
  • Memory builds over time. BuddyPro learns preferences, facts, and context from API interactions, the same way it does from Telegram chats.
  • Stateless mode available. Set x_buddy_saveToHistory: false to make a request that doesn't persist anything — no chat history, no memory updates, no profile changes. See Stateless Mode.

Do not send conversation history in the messages array. Send only the current user message. BuddyPro stores and manages conversation context server-side.

Privacy & Data Access

The Client API provides full data ownership for end-users. Unlike the Owner API (where the instance owner can switch to any test profile they created), the Client API is designed around user privacy:

  • Your API key is yours only. The BuddyPro instance owner cannot see your key.
  • Your profile is private. The instance owner cannot switch to your personal Telegram profile through the bot — Telegram user IDs are numeric and the /test command blocks numeric IDs entirely.
  • Your isolated profiles are protected. Profiles you create via the user field are attributed to your own API key. The instance owner cannot switch to them — the bot enforces that you can only switch to profiles created by your own keys.

What this means in practice:

The Client API is safe to use for personal integrations, automations, and tools where you want programmatic access to your own BuddyPro profile. You control your data through the same key you generated.

Authentication

Getting a Client API Key

Send this command to your BuddyPro bot in Telegram:

/generateClientApiKey:my-app

The name (:my-app) is optional — if omitted, a name is auto-generated. You'll receive a key starting with bapi_B2C_.

Store this key securely — it won't be shown again. To revoke it: /invalidateApiKey:my-app (you can use the key name or the raw key string)

After generating the key, you must set up credit billing before making your first API request.

NOTE: By default, requests use your own personal BuddyPro profile — messages are saved to your history and contribute to your memory. Use the user field to create additional isolated profiles with separate conversation history and memory (e.g., for different projects or contexts). See User Isolation.

Setting Up Credit Billing

The Client API requires prepaid credits via Stripe. After generating your key, run:

/setupApiCredits:100:20

This opens a Stripe checkout where you purchase your initial credit top-up. The two parameters are:

ParameterDescriptionMinimumMaximum
topUpAmountAmount in USD to deposit when credits run low$10$10,000
rechargeAtCredit balance threshold that triggers an automatic top-up$2$10,000

Example: /setupApiCredits:100:20 — buy $100 initially, automatically recharge with $100 whenever your balance drops below $20.

Credits are automatically recharged via your saved payment method when your balance falls below the rechargeAt threshold. You don't need to manually top up after the initial setup.

Payment goes to the instance, not to BuddyPro. Your credit checkout and saved payment method are processed by the BuddyPro instance you use (its owner), who sets the per-request price. The amount deducted from your balance per request is that instance's price.

Setup requirements. /setupApiCredits returns an error if:

  • You don't have an active subscription to the instance: "An active subscription is required to set up Client API credits."
  • The instance isn't set up to accept API payments: "This instance is not set up to accept API credit payments yet. Please contact the instance owner."

Once billing is active, use /changeApiCreditsTopUp (below) to adjust the amounts — calling /setupApiCredits again returns an error telling you billing is already set up.

Changing Credit Settings

To change your top-up amount or recharge threshold without triggering a new Stripe checkout:

/changeApiCreditsTopUp:20:5

Updates the auto-recharge to $20 and the threshold to $5. Your existing billing relationship is preserved — no new checkout required.

API Key Management

CommandDescription
/generateClientApiKey:{name}Create a new Client API key (name is optional)
/invalidateApiKey:{name or bapi_B2C_...}Revoke a key by its name or the raw key string
/getApiStatsList all your active API keys and usage
/setupApiCredits:{topUp}:{rechargeAt}Set up billing (first time — opens Stripe checkout)
/changeApiCreditsTopUp:{topUp}:{rechargeAt}Update auto-recharge amount and threshold

Authenticating Requests

Pass your API key via the Authorization header:

Authorization: Bearer bapi_B2C_xxxxxxxxxxxx

Endpoint

POST https://api.buddypro.ai/v1/chat/completions
Authorization: Bearer bapi_B2C_xxxxxxxxxxxx
Content-Type: application/json

Request

Content Input

Standard OpenAI messages array. BuddyPro extracts the last user message for processing.

Only one user message is allowed. BuddyPro manages conversation history server-side — do not send conversation turns. System and assistant messages are ignored.

Text only (string content):

{
"messages": [
{ "role": "user", "content": "Hello, how are you?" }
]
}

Multimodal (array content):

{
"messages": [
{
"role": "user",
"content": [
{ "type": "text", "text": "Describe this image" },
{ "type": "image_url", "image_url": { "url": "https://example.com/photo.jpg" } }
]
}
]
}

Content Part Types

When using array content inside messages[].content:

Text

{ "type": "text", "text": "What is the weather today?" }

Max 50,000 characters per text part.

Image (image_url)

{ "type": "image_url", "image_url": { "url": "https://example.com/photo.jpg" } }

Supported URL types:

  • HTTPS URL — must be publicly accessible
  • Data URIdata:image/png;base64,iVBORw0KGgo...

Max 5 images per request. Max 40 MB per remote download.

Audio Input (input_audio)

{
"type": "input_audio",
"input_audio": {
"data": "<base64>",
"format": "mp3"
}
}

Fields:

FieldTypeDescription
datastringBase64-encoded audio data or URL
formatstringAudio format: mp3, wav, ogg, aac, flac
type"url" | "base64"Optional data type hint. Default: base64

Audio via URL:

{
"type": "input_audio",
"input_audio": {
"data": "https://example.com/audio.mp3",
"type": "url",
"format": "mp3"
}
}

Audio Output (TTS via Modalities)

To request TTS audio output, use the OpenAI-style modalities and audio fields:

{
"modalities": ["text", "audio"],
"audio": { "format": "mp3" },
"messages": [
{
"role": "user",
"content": [
{ "type": "input_audio", "input_audio": { "data": "<base64>", "format": "mp3" } }
]
}
]
}
  • When modalities includes "audio", TTS is enabled
  • audio.format defaults to "mp3" if omitted
  • TTS only applies when audio input is present in the request
  • audio.voice is accepted but ignored — voice is set by the bot owner

Request Fields Reference

FieldTypeRequiredDescription
messagesarrayYesOpenAI-format messages. Must contain exactly 1 user message.
modalities["text"] | ["text", "audio"]Output types. Include "audio" to enable TTS
audioobjectAudio config: { "format": "mp3"|"wav" }
userstringCustom user identifier for an isolated profile. See User Isolation
x_buddy_saveToHistorybooleanWhen false, nothing is saved to history, memory, or profile. Default: true. See Stateless Mode

Prompt-override fields are not available in the Client API. x_buddy_systemPrompt, x_buddy_systemPromptMode, and x_buddy_rolePrompt are not supported for Client API keys — the instance owner's system and role prompts cannot be overridden per request. Sending any of these fields returns a 400 unsupported_parameter error.

Client Request ID

Provide via the X-Client-Request-Id HTTP header (max 64 characters, alphanumeric + hyphens + underscores):

curl -X POST https://api.buddypro.ai/v1/chat/completions \
-H "Authorization: Bearer bapi_B2C_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "X-Client-Request-Id: my-app_req-42" \
-d '{ "messages": [{ "role": "user", "content": "Hello!" }] }'

User Isolation

By default, API requests use your personal BuddyPro profile — all conversations are saved to your history and contribute to your memory.

To create isolated profiles with separate conversation history and memory, use the user field. Each unique user value creates a fully separate profile — useful for different projects, personas, or contexts.

ModeHow to activateBehavior
Personal profile (default)Omit userUses your own profile (history, settings, memory)
Isolated profileSet user to a custom identifierCreates a separate profile per value — own history, memory, settings
StatelessSet x_buddy_saveToHistory: falseNothing is persisted. Can be combined with either mode

Isolated profile example:

{
"user": "work-assistant",
"messages": [
{ "role": "user", "content": "Help me prepare for my 3pm meeting." }
]
}

Validation rules for user:

  • Alphanumeric characters, hyphens, underscores, and dots only (a-z, A-Z, 0-9, -, _, .)
  • Cannot be a purely numeric value
  • Max 128 characters, no spaces

Stateless Mode

Set x_buddy_saveToHistory: false to make a request that does not persist anything. In stateless mode:

  • Nothing is saved to chat history
  • No updates to long-term memory
  • No profile updates or preference learning
  • The AI still responds normally using existing context

Example — stateless Q&A:

{
"x_buddy_saveToHistory": false,
"messages": [
{ "role": "user", "content": "What is the best way to start a business?" }
]
}

Response

Response Headers

HeaderDescription
x-request-idServer-generated unique request ID (always present)
x-client-request-idClient-supplied request ID echoed back (if provided)
Content-Typeapplication/json

Success — Text Only

{
"id": "chatcmpl-req_abc123def456",
"object": "chat.completion",
"created": 1710964800,
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Hello! How can I help you today?"
},
"finish_reason": "stop"
}
]
}

Success — Image Output

When BuddyPro generates an image, it appears in message.image:

{
"id": "chatcmpl-req_def456",
"object": "chat.completion",
"created": 1710964800,
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Here's the image you requested:",
"image": {
"id": "image_req_def456_generated_image.png",
"data": "iVBORw0KGgo...",
"media_type": "image/png",
"file_name": "generated_image.png",
"caption": "A sunset over the ocean"
}
},
"finish_reason": "stop"
}
]
}

Success — Audio Output (Music / Meditation)

Audio from music or meditation features is always returned regardless of modalities:

{
"id": "chatcmpl-req_ghi789",
"object": "chat.completion",
"created": 1710964800,
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"audio": {
"id": "audio_req_ghi789_response.ogg",
"data": "<base64>",
"format": "ogg",
"transcript": null,
"media_type": "audio/ogg",
"file_name": "response.ogg"
}
},
"finish_reason": "stop"
}
]
}

Success — Text + TTS Audio

When TTS is enabled via modalities and audio input was sent:

{
"id": "chatcmpl-req_abc123",
"object": "chat.completion",
"created": 1710964800,
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Why don't scientists trust atoms? Because they make up everything!",
"audio": {
"id": "audio_req_abc123_response.mp3",
"data": "<base64>",
"format": "mp3",
"transcript": "Why don't scientists trust atoms? Because they make up everything!",
"media_type": "audio/mpeg",
"file_name": "response.mp3"
}
},
"finish_reason": "stop"
}
]
}

When audio output is present, transcript contains the same text as content (the concatenated text response).

Response Fields Reference

Top-level

FieldTypeDescription
idstringUnique completion ID: chatcmpl-{requestId}
objectstringAlways "chat.completion"
creatednumberUnix timestamp (seconds) of request start
choicesarrayArray with single choice (index 0)

Note: Request ID and processing time metadata are available via response headers (X-Request-Id, X-Client-Request-Id) — they are not included in the response body.

choices[0].message

FieldTypeDescription
rolestringAlways "assistant"
contentstring | nullConcatenated text response. null if only media
audioobject | undefinedAudio output (first audio item). See below
imageobject | undefinedImage output (first image item). See below

message.audio (OpenAiAudioOutput)

FieldTypeDescription
idstringAudio identifier: audio_{requestId}_{fileName}
datastringBase64-encoded audio data
formatstringAudio format (e.g., mp3, ogg, wav)
transcriptstring | undefinedText transcript (same as content when TTS)
media_typestringMIME type (e.g., audio/mpeg, audio/ogg)
file_namestringSuggested filename

message.image (OpenAiImageOutput — BuddyPro Extension)

FieldTypeDescription
idstringImage identifier: image_{requestId}_{fileName}
datastringBase64-encoded image data
media_typestringMIME type (e.g., image/png)
file_namestringSuggested filename
captionstringImage caption/description

Error Responses

Error Response Format

All errors use a structured format with an error object:

{
"error": {
"message": "Invalid or inactive API key",
"type": "authentication_error",
"statusCode": 401,
"code": "invalid_api_key",
"param": null
}
}

Important: Always inspect the response body for the error field — do not rely solely on the HTTP status code. In certain conditions, the HTTP status code may be 200 even when the response body contains an error.

Error Fields

FieldTypeDescription
error.messagestringHuman-readable error description
error.typestringError category
error.statusCodenumberHTTP status code
error.codestring | nullMachine-readable error code
error.paramstring | nullThe request parameter that caused the error

Error Types

HTTP StatustypeDescription
400invalid_request_errorMalformed request, missing fields, invalid content
401authentication_errorMissing or invalid API key
402payment_requiredBilling not set up, insufficient credits, or instance billing unavailable (Client API specific — see below)
403permission_errorInsufficient permissions
405method_not_allowedWrong HTTP method
410goneDeprecated endpoint no longer available
429rate_limit_errorRate limit exceeded
500server_errorInternal server error

Common Error Codes

CodeMeaning
invalid_jsonRequest body is not valid JSON
missing_required_parameterRequired field missing
missing_api_keyNo API key provided in Authorization header
invalid_api_keyAPI key not found or inactive
invalid_valueField has wrong type or invalid value
invalid_text_contentText empty or exceeds 50,000 char limit
invalid_content_typeUnknown content part type
invalid_contentContent has no usable items
invalid_media_dataMedia data invalid, download failed, or exceeds size limit
invalid_media_typeUnsupported MIME type
invalid_audio_formatUnsupported audio format
invalid_image_countToo many images (max 5)
invalid_parameterInvalid parameter value (e.g., bad user or x_buddy_saveToHistory)
unsupported_parameterA parameter that is not supported for Client API keys was sent (e.g., x_buddy_systemPrompt, x_buddy_systemPromptMode, x_buddy_rolePrompt)
insufficient_permissionsAPI key lacks required permissions, or the instance owner has disabled the Client API (see Client API Disabled)
endpoint_deprecatedAPI version has been deprecated and is no longer available
rate_limit_exceededMore than 30 requests/minute

Client API-Specific Errors (HTTP 402)

The Client API adds four billing-related error codes. All use type: "payment_required":

HTTP StatuscodeDescription
402billing_not_set_upNo billing configured yet. Run /setupApiCredits:{topUp}:{rechargeAt} in Telegram first.
402insufficient_creditsYour credit balance is zero or negative and the auto-recharge failed or is on cooldown — check your payment method. Recharge retries automatically on the next request.
402insufficient_credits_rechargingYour credit balance was zero or negative, but this request just triggered a successful auto-recharge payment — the credits arrive within seconds. The response carries a Retry-After: 5 header; simply retry shortly.
402owner_billing_unavailableThe instance you're using is temporarily unable to bill for usage (the instance's own billing balance is depleted). This is on the instance owner's side, not yours — retry later.

Example — billing not set up:

{
"error": {
"message": "Billing not set up. Please set up billing to use the Buddy API. Call /setupApiCredits:{topUpAmount}:{rechargeAt} first.",
"type": "payment_required",
"statusCode": 402,
"code": "billing_not_set_up",
"param": null
}
}

Example — insufficient credits:

{
"error": {
"message": "Insufficient credits. Auto-recharge failed or is in cooldown — please check your payment method and try again later.",
"type": "payment_required",
"statusCode": 402,
"code": "insufficient_credits",
"param": null
}
}

Example — insufficient credits, recharge in flight (response includes Retry-After: 5):

{
"error": {
"message": "Insufficient credits. An automatic recharge was just initiated and payment succeeded — credits will be available shortly. Please retry.",
"type": "payment_required",
"statusCode": 402,
"code": "insufficient_credits_recharging",
"param": null
}
}

Example — instance billing unavailable:

{
"error": {
"message": "Service is temporarily unavailable for billing reasons. Please try again later.",
"type": "payment_required",
"statusCode": 402,
"code": "owner_billing_unavailable",
"param": null
}
}

Client API Disabled (HTTP 403)

The Client API is an owner opt-in and can be disabled by the instance owner at any time. While it is disabled, every request — including with previously issued, valid keys — is rejected with 403 insufficient_permissions. Keys are not revoked; they resume working as soon as the owner re-enables the Client API.

{
"error": {
"message": "The Client API is not enabled for this instance. The instance owner must enable it first.",
"type": "permission_error",
"statusCode": 403,
"code": "insufficient_permissions",
"param": null
}
}

Rate Limits

  • 30 requests per minute per API key

Quick Start

Step 1 — Generate a key

/generateClientApiKey:my-app

Step 2 — Set up billing

/setupApiCredits:100:20

Complete the Stripe checkout. Your account now has $100 in credits and will auto-recharge when your balance drops below $20.

Step 3 — Make your first request

curl -X POST https://api.buddypro.ai/v1/chat/completions \
-H "Authorization: Bearer bapi_B2C_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "role": "user", "content": "Hello! What do you know about me?" }
]
}'

curl — Stateless Mode

curl -X POST https://api.buddypro.ai/v1/chat/completions \
-H "Authorization: Bearer bapi_B2C_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"x_buddy_saveToHistory": false,
"messages": [
{ "role": "user", "content": "What is the best way to start a profitable business?" }
]
}'

curl — Isolated Profile

curl -X POST https://api.buddypro.ai/v1/chat/completions \
-H "Authorization: Bearer bapi_B2C_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"user": "work-assistant",
"messages": [
{ "role": "user", "content": "Help me write a professional email." }
]
}'

curl — Multimodal (Image + Text)

curl -X POST https://api.buddypro.ai/v1/chat/completions \
-H "Authorization: Bearer bapi_B2C_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"role": "user",
"content": [
{ "type": "text", "text": "What is in this image?" },
{ "type": "image_url", "image_url": { "url": "https://example.com/photo.jpg" } }
]
}
]
}'

curl — Audio Input with TTS Output

curl -X POST https://api.buddypro.ai/v1/chat/completions \
-H "Authorization: Bearer bapi_B2C_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"modalities": ["text", "audio"],
"audio": { "format": "mp3" },
"messages": [
{
"role": "user",
"content": [
{ "type": "input_audio", "input_audio": { "data": "<base64>", "format": "mp3" } }
]
}
]
}'

Limitations

LimitationDetail
No streamingStreaming is not supported yet
Single user messageOnly 1 user message in messages array (BuddyPro manages history)
No model selectionmodel field is accepted but ignored — BuddyPro has its own model implementation
No usage statsusage object is not included in responses
First media winsOnly the first audio and first image in the response are surfaced per choice
Voice not controllableaudio.voice is accepted but ignored — voice is set by the bot owner

Media Limits

  • Max 5 images per request
  • Max 40 MB per media download (URL-fetched media)
  • Max 50,000 characters per text content part

Important Notes

  • Do not send conversation history — send only the current user message. BuddyPro stores and manages conversation context internally.
  • Credit billing is required before your first request. Set it up once with /setupApiCredits:{topUp}:{rechargeAt}. It requires an active subscription to the instance, and the instance must accept API payments.
  • Billing is handled by your instance. Credit checkouts and the per-request price are set by the BuddyPro instance you use (its owner), not by BuddyPro directly.
  • Credits auto-recharge when your balance falls below the configured threshold, using your saved Stripe payment method.
  • Your data is yours. The instance owner cannot read your conversation history or switch to your profile or your isolated profiles through the bot interface.
  • SSRF protection: URLs pointing to private/internal network addresses are blocked.