Skip to main content

BuddyPro End-user API (Client API)

version: 1.3 (2026-09-18)

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).

NOTE: A Client API key always carries plain-user rights, even when the person who generated it owns the instance or is on its team. Instance management commands (/enableClientApi, /setApiClientMarkup and the like) are refused with permission_denied. Rights cover permissions only: the key still acts as the profile its requests run on — that profile's conversation history, memory and plain-user commands — and usage is still billed to the key's owner.

The subscription must stay active. Access is tied to a live subscription, not to your message allowance: a used-up monthly message limit does not close the API, but a cancelled, lapsed, or unpaid subscription does — with a 403 (see Subscription No Longer Active).

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 URI — data: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"
}
}

Document / File (file)​

Attach a document (PDF, Office file, text, etc.) as an OpenAI-style file content part. BuddyPro extracts the document to text server-side and uses it as context — exactly like sending a document to the bot on Telegram or mobile. The model does not receive the raw file bytes, so the assistant's reply is a normal text (or media) response — document inputs are not echoed back.

{
"type": "file",
"file": {
"filename": "report.pdf",
"file_data": "data:application/pdf;base64,<base64>"
}
}

Fields:

FieldTypeDescription
filenamestringSuggested file name (used to infer type when the MIME is ambiguous)
file_datastringData URI: data:<mime>;base64,<base64>. Mutually exclusive with file.url
urlstringBuddyPro extension — an http(s) URL to a hosted file to download instead of inline file_data. The document type comes from the file bytes (PDF, Office files) or the server's Content-Type; a generic Content-Type (application/octet-stream, text/plain) is refined by the filename / URL extension when the bytes are consistent with it, otherwise it is kept

Document via URL (BuddyPro extension):

{
"type": "file",
"file": {
"filename": "report.pdf",
"url": "https://example.com/report.pdf"
}
}

file.file_id is not supported — BuddyPro has no Files API. Provide the document inline via file_data or hosted via url.

Audio is not sent as a file part — use the separate input_audio part for audio.

Supported document MIME types: application/pdf, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document (docx), application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet (xlsx), application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.presentation (pptx), text/plain, text/csv, text/html, text/markdown, application/json, application/xml, text/xml, and the video types video/mp4, video/quicktime, video/webm, video/x-msvideo, video/mpeg (transcribed to text). application/octet-stream is accepted as an unknown-type fallback. Unsupported MIME types return error code invalid_media_type.

Max 5 documents per request. Max 40 MB per document (URL-fetched or decoded base64).

Large files: prefer file.url over inline file_data. Inline base64 rides the request body, which is capped at ~6 MB (~4 MB of actual file) well before the 40 MB validation cap — this applies to all inline media, not just documents. See Media Limits.


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
audioobject—Audio config: { "format": "mp3"|"wav" }
userstring—Custom user identifier for an isolated profile. See User Isolation
x_buddy_saveToHistoryboolean—When 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 — Multiple Images​

When a response contains more than one image, image holds the first (for OpenAI SDK compatibility) and the complete ordered set is additionally provided in x_buddy_images:

{
"id": "chatcmpl-req_multi123",
"object": "chat.completion",
"created": 1710964800,
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Here are the images you requested:",
"image": {
"id": "image-1-req_multi123-first.png",
"data": "iVBORw0KGgo...",
"media_type": "image/png",
"file_name": "first.png",
"caption": "A sunrise over the mountains"
},
"x_buddy_images": [
{
"id": "image-1-req_multi123-first.png",
"data": "iVBORw0KGgo...",
"media_type": "image/png",
"file_name": "first.png",
"caption": "A sunrise over the mountains"
},
{
"id": "image-2-req_multi123-second.png",
"data": "iVBORw0KGgo...",
"media_type": "image/png",
"file_name": "second.png",
"caption": "A sunset over the ocean"
}
]
},
"finish_reason": "stop"
}
]
}

The same pattern applies to audio: multiple audio items populate x_buddy_audios (with x_buddy_audios[0] equal to audio).

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
x_buddy_audiosarray | undefinedBuddyPro extension. All audio items, in order. Present only when more than one audio item is returned; x_buddy_audios[0] equals audio. Each item has the same shape as message.audio.
x_buddy_imagesarray | undefinedBuddyPro extension. All image items, in order. Present only when more than one image item is returned; x_buddy_images[0] equals image. Each item has the same shape as message.image.

Returning all media. The singular audio / image fields stay single objects for OpenAI SDK compatibility (SDKs deserialize message.audio into a typed object). When a response carries more than one item of a type, the complete ordered set is additionally provided in the x_buddy_audios / x_buddy_images arrays — OpenAI SDK clients simply ignore these extension fields. For a single (or zero) item of a type, the array is omitted and the response is unchanged. When audio output is present, transcript is set on the first audio item only.

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 (covers unsupported image, audio, and document MIME types)
invalid_audio_formatUnsupported audio format
invalid_image_countToo many images (max 5)
invalid_document_countToo many documents (max 5 file parts)
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)
subscription_stoppedThe subscription behind the API key was cancelled and its paid period is over (see Subscription No Longer Active)
subscription_unpaidThe subscription behind the API key has a failed payment or an unpaid invoice
subscription_requiredThe free trial behind the API key ended without a subscription
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
}
}

Subscription No Longer Active (HTTP 403)​

Client API access follows your subscription to the BuddyPro instance, not your message allowance. While the subscription is live the API keeps working — including when your monthly message limit for the Telegram chat is used up, because API requests are paid from credits and never spend that allowance. If the subscription itself ends, the API closes with a 403 and type: "permission_error":

HTTP StatuscodeDescription
403subscription_stoppedYour subscription was cancelled and its paid period is over. Restart it with /start in the chat. A cancelled subscription keeps working until the end of the period you already paid for.
403subscription_unpaidYour subscription payment failed repeatedly or an invoice is unpaid. Update your payment method.
403subscription_requiredYour free trial ended without a subscription. An active subscription is required.

This check runs before the credit checks, so a lapsed subscription is never charged an auto-recharge on the way to being refused — and it is always evaluated on the account that owns the API key, whether or not the request carries a user field.

Example — subscription no longer active:

{
"error": {
"message": "Your Buddy subscription is no longer active. Please restart it with /start in the chat to restore API access.",
"type": "permission_error",
"statusCode": 403,
"code": "subscription_stopped",
"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 — Document (File + 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": "Summarize this report." },
{ "type": "file", "file": { "filename": "report.pdf", "file_data": "data:application/pdf;base64,<base64>" } }
]
}
]
}'

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 5 documents per request (file content parts) — exceeding this returns error code invalid_document_count
  • Max 40 MB per media download (URL-fetched or decoded base64 — images, audio, and documents)
  • Inline base64 is transport-bounded (~6 MB request body). The whole request body must fit within a ~6 MB request-body size limit, so inline base64 media — an image_url data URI, input_audio.data, or file_data — is effectively capped near ~4 MB of actual file (base64 adds ~33%), well below the 40 MB cap above. For larger files send a URL instead (image_url HTTPS URL, input_audio with type: "url", or file.url): it is fetched server-side and gets the full 40 MB budget.
  • Max 50,000 characters per text content part
  • Supported document types: PDF, Word (.doc/.docx), Excel (.xls/.xlsx), PowerPoint (.ppt/.pptx), plain text, CSV, HTML, Markdown, JSON, XML, and the video types mp4/quicktime/webm/avi/mpeg (transcribed). Unsupported MIME types return invalid_media_type. See Document / File (file)

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.

Version History​

VersionReleasedChanges
1.32026-09-18Document (file) content part with inline file_data or file.url; x_buddy_images / x_buddy_audios arrays when a response carries more than one image or audio item; invalid_document_count; Media Limits reworked (documents, inline-base64 transport bound)
1.22026-09-10Subscription No Longer Active (HTTP 403, subscription_* codes); End-user keys always carry plain-user rights
1.12026-07-17Reseller model — owner opt-in gate (keys and /setupApiCredits work only once the instance enables the End-user API), per-request price set by the instance with its markup, HTTP 402 mapped to payment_required, 402 distinguishing a successful auto-recharge
1.02026-07-17Initial release (shipped together with 1.1)