Skip to content

Record a purchase

POST
/v1/server/purchases
curl --request POST \
--url https://app.mondochat.io/v1/server/purchases \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Mondochat-App-Id: <Mondochat-App-Id>' \
--data '{ "buyer": "bob", "currency": "EUR", "external_ref": "order-1042", "item": { "kind": "show", "title": "Private show" }, "price_minor": 1500, "seller": "alice" }'

Records a purchase made outside the chat. Takes the app id and the server secret, and an Idempotency-Key header; a repeat of the external_ref is deduped. A missing buyer or seller is created from buyer_profile or seller_profile; without a profile a missing user answers 404, and a guest answers 422. It opens the conversation of the two when there is none, started by the buyer, and posts one purchase card from the buyer whatever the policy and even when either blocked the other. Users are created in the same transaction as the purchase, so a refused call creates nothing. See https://docs.mondochat.io/guides/commerce/.

Idempotency-Key
Any of:
string
>= 1 characters <= 255 characters
Media typeapplication/json
ServerPurchaseCreate

A purchase made outside the chat, recorded from your server.

object
buyer
required
Buyer

The buyer, as on your site.

string
/^[A-Za-z0-9._:@-]{1,128}$/
buyer_profile
Any of:
Profile

A user’s profile, as your server sets it.

object
avatar
Any of:
string
<= 2048 characters /^https://\S+$/
lang
Any of:
string
Allowed values: it en es fr
name
required
Name

Display name.

string
>= 1 characters <= 100 characters
perms
Any of:
Perms

Per-user overrides carried in the perms claim; a null field changes nothing.

object
block
Any of:
boolean
buy
Any of:
boolean
call
Any of:
boolean
message
Any of:
boolean
messages_per_minute
Any of:
integer
>= 1
messages_to_unanswered
Any of:
integer
new_conversations_per_day
Any of:
integer
offers
Any of:
boolean
photo_consent_required
Any of:
boolean
photos
Any of:
boolean
photos_per_day
Any of:
integer
require_vouch
Any of:
boolean
see_presence
Any of:
boolean
start_conversation
Any of:
boolean
voice_per_day
Any of:
integer
role
Any of:
string
/^[A-Za-z0-9_-]{1,32}$/
tier
Any of:
string
/^[A-Za-z0-9_-]{1,32}$/
currency
required
Currency

ISO 4217 currency of the price.

string
/^[A-Z]{3}$/
external_ref
required
External Ref

Your reference for the purchase; a repeat with the same one is deduped.

string
>= 1 characters <= 200 characters
item
required
PurchaseItem

The item that was bought.

object
description
Any of:
string
<= 2000 characters
id
Any of:
string
kind
Any of:
string
title
required
Title

The item’s name.

string
>= 1 characters <= 200 characters
price_minor
required
Price Minor

The price in minor units.

integer
seller
required
Seller

The seller, as on your site.

string
/^[A-Za-z0-9._:@-]{1,128}$/
seller_profile
Any of:
Profile

A user’s profile, as your server sets it.

object
avatar
Any of:
string
<= 2048 characters /^https://\S+$/
lang
Any of:
string
Allowed values: it en es fr
name
required
Name

Display name.

string
>= 1 characters <= 100 characters
perms
Any of:
Perms

Per-user overrides carried in the perms claim; a null field changes nothing.

object
block
Any of:
boolean
buy
Any of:
boolean
call
Any of:
boolean
message
Any of:
boolean
messages_per_minute
Any of:
integer
>= 1
messages_to_unanswered
Any of:
integer
new_conversations_per_day
Any of:
integer
offers
Any of:
boolean
photo_consent_required
Any of:
boolean
photos
Any of:
boolean
photos_per_day
Any of:
integer
require_vouch
Any of:
boolean
see_presence
Any of:
boolean
start_conversation
Any of:
boolean
voice_per_day
Any of:
integer
role
Any of:
string
/^[A-Za-z0-9_-]{1,32}$/
tier
Any of:
string
/^[A-Za-z0-9_-]{1,32}$/

Successful Response

Media typeapplication/json
Purchase

A purchase of an item by a buyer from a seller.

object
buyer_id
required
Buyer Id

The buyer’s id.

string format: uuid
conversation_id
required
Any of:
string format: uuid
created_at
required
Created At

When the purchase was created.

string format: date-time
currency
required
Currency

ISO 4217 currency of the price.

string
external_ref
Any of:
string
id
required
Id

The purchase’s id.

string format: uuid
item
required
PurchaseItem

The item that was bought.

object
description
Any of:
string
<= 2000 characters
id
Any of:
string
kind
Any of:
string
title
required
Title

The item’s name.

string
>= 1 characters <= 200 characters
mode
required
Mode

How it is paid: the app’s commerce.payment_mode, or external for a purchase recorded from your server.

string
Allowed values: server_charge page_callback checkout_url external
price_minor
required
Price Minor

The price in minor units.

integer
seller_id
required
Seller Id

The seller’s id.

string format: uuid
status
required
Status

pending until paid; insufficient when the balance was short.

string
Allowed values: pending paid insufficient failed cancelled

Example

{
"buyer_id": "0199d6a0-1000-7000-8000-000000000002",
"conversation_id": "0199d6a0-2000-7000-8000-000000000001",
"created_at": "2026-11-01T09:30:00Z",
"currency": "EUR",
"external_ref": "order-1042",
"id": "0199d6a0-7000-7000-8000-000000000001",
"item": {
"id": "private-show",
"kind": "show",
"title": "Private show"
},
"mode": "server_charge",
"price_minor": 1500,
"seller_id": "0199d6a0-1000-7000-8000-000000000001",
"status": "paid"
}

Problem

Media typeapplication/problem+json

An RFC 9457 problem: the body of every error answer.

object
code
required

The stable error code to branch on, such as policy_denied.

string
detail

What went wrong this time, when there is more to say.

string | null
errors

For validation, one entry per invalid field.

Array<object>

One invalid field.

object
loc

The path to the field.

array
msg

What is wrong with it.

string
instance

The path of the request.

string
reason

For policy_denied and limit_reached, the rule or limit that refused the request; for forbidden, a short cause such as you_blocked; for banned, temporary when the ban expires.

string
status
required

The HTTP status code.

integer
title
required

A short summary of the problem.

string
type
required

A URL that names the problem, https://app.mondochat.io/problems/<code>.

string

Example

{
"code": "policy_denied",
"detail": null,
"instance": "/v1/conversations/0199d6a0-2000-7000-8000-000000000001",
"reason": "pins",
"status": 403,
"title": "Policy denied",
"type": "https://app.mondochat.io/problems/policy_denied"
}