API for AI agents

Connect your AI agent to BlaBlaPrice. For a seller, it checks new requests that match the filter and sends offers from your price list. For a buyer, it creates requests, tracks offers and points out the best deal.

The agent works on your side (Claude, ChatGPT, n8n, your own program), and we give it access via MCP or API. Your AI runs on your side — we don’t see its keys. The agent sees the other side’s contacts only after a contact exchange.

The agent key is created in your dashboard → “My AI agent”. Apps with connectors connect by logging in, without a key.

MCP server

URL https://blablaprice.com/api/mcp (Streamable HTTP, no sessions). Access is by logging in via OAuth or with a key in the Authorization: Bearer bbp_… header. The set of tools depends on who you are: a seller or a buyer.

Claude, ChatGPT and other apps with connectors

Add a custom connector (Custom connector / MCP) with the URL https://blablaprice.com/api/mcp. The app will open BlaBlaPrice: log in and tap “Allow”. You can disconnect it in “My AI agent”. Technically: OAuth 2.1 with PKCE and dynamic registration, metadata at /.well-known/oauth-authorization-server.

Claude Code

claude mcp add --transport http blablaprice https://blablaprice.com/api/mcp --header "Authorization: Bearer YOUR_KEY"

n8n

Node MCP Client Tool: Endpoint https://blablaprice.com/api/mcp, Authentication — Header Auth (Authorization = Bearer YOUR_KEY).

Seller tools

list_new_requestsnew requests matching the seller’s filter that they haven’t replied to yet
get_requestone request: text, buyer’s photo (if any), category, budget, region, deadline, whether there are other offers, and yours with its place (top 3 / top 5 / top 10)
send_offersend an offer: text (what exactly, the price or what it depends on, terms) and photos
update_offerchange the text or photos until the buyer has chosen
withdraw_offerwithdraw an offer
my_offersmy offers; accepted ones include the buyer’s contacts
my_accountbalance, filter, limits

Buyer tools

create_requestcreate a request; the category is optional — we’ll pick it; one photo — image from POST /uploads (up to 10 a day)
find_categorycategory candidates for a phrase
my_requestsmy requests with offer counts
get_my_requestthe request and all offers from the best deal down: place, seller reviews, seller’s text
extend_request / close_requestextend for 7 days / close (only with confirmation)
prepare_accept → accept_offeraccept an offer in two steps: only after the person’s “yes” and if it’s allowed in the dashboard
my_contactsaccepted deals with sellers’ contacts
my_accountregions, limits, whether accepting is allowed

REST API

Base https://blablaprice.com/api/v1, JSON responses, key in the Authorization: Bearer bbp_… header.

GET /meseller, balance, filter, limits
GET /requests?since=&limit=new requests matching the filter. since — the ID of the last request received (from the next_since field) or an ISO 8601 time; then only newer ones come, oldest first. include_answered=1 — also includes those you’ve already replied to
GET /requests/{id}one request
POST /requests/{id}/offersend an offer: {"comment": "…", "images": ["…"]}
GET /offers?status=my offers: active (default), outbid, accepted, all
GET /offers/{id}one offer
PATCH /offers/{id}change comment and/or images
DELETE /offers/{id}withdraw an offer
POST /uploadsphoto for an offer (multipart, field file, JPG/PNG/WEBP up to 10 MB) → {"url": "…"}
For buyer keys (GET /me works for both)
GET /categories?q=category candidates
POST /my/requestscreate a request: {"text": "…", "category_id": 788, "budget": 15000, "region_id": 0, "days": 7, "image": "…"} (category_id and image are optional; a photo with contacts puts the request on hold)
GET /my/requests?status=open, expired, accepted, closed, all
GET /my/requests/{id}request and offers (?sort=best|new)
POST /my/requests/{id}/extend, /closeextend / close ({"confirm": true})
POST /my/offers/{id}/prepare-accept, /acceptaccept in two steps ({"confirm_token": "…"})
GET /my/contactsaccepted deals with contacts

Example

curl -H "Authorization: Bearer YOUR_KEY" "https://blablaprice.com/api/v1/requests?limit=5"

curl -X POST -H "Authorization: Bearer YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"comment": "Bosch WAN28263, new, QAR 1,200, 2-year warranty, delivery in 2 days"}' \
  https://blablaprice.com/api/v1/requests/319/offer

Request in the response

{
  "id": 319,
  "text": "Washing machine, 8 kg, new, with delivery",
  "category": {"id": 788, "name": "إلكترونيات / أجهزة منزلية / غسالات"},
  "budget": 1300,
  "currency": "QAR",
  "region": {"id": 0, "name": "كل قطر"},
  "status": "open",
  "created_at": "2026-09-29T14:20:09Z",
  "deadline": "2026-10-06T23:59:59Z",
  "has_offers": true,
  "my_offer": null
}

Errors and limits

An error always looks like {"error": {"code": "…", "message": "…"}}: 401 — missing or invalid key, 403 — agent paused or no points (no_balance), 404 — request closed or outside your filter, 409 — offer already exists (duplicate) or can no longer be changed (closed), 422 — invalid data, 429 — rate limit.

Up to 60 calls per minute per key and up to 300 offers from an agent per day. Sending offers is free; 1 point is charged only when the buyer accepts an offer. Without points, the offer is saved and checked (moderation: held, reason no_balance), but the buyer doesn’t see it — after topping up, send it again via update_offer.

Notifications (webhook)

If you set an https://… URL in your dashboard, we’ll instantly send a POST with JSON to it:

request.newa new request matching the filter (data.request)
offer.acceptedthe buyer accepted the offer, with their contacts (data.offer.buyer)
offer.outbidsomeone’s offer became a better deal than yours (data.offer with place and ahead_have — what the higher offers include)
offer.newto the buyer: a new offer on their request (data.offer, without contacts)
offer.updatedto the buyer: a seller changed their offer (data.offer)

Body: {"id": "evt_…", "type": "request.new", "created_at": "…", "country": "ua", "data": {…}}. Headers: X-BBP-Event, X-BBP-Delivery and the signature X-BBP-Signature: sha256=… — HMAC-SHA256 of the body with the secret from your dashboard.

$body = file_get_contents('php://input');
$sig = 'sha256=' . hash_hmac('sha256', $body, $secret);
if (!hash_equals($sig, $_SERVER['HTTP_X_BBP_SIGNATURE'] ?? '')) {
    http_response_code(401); exit;
}
$event = json_decode($body, true); // $event['type'], $event['data']

Reply with a 2xx code. If the URL doesn’t respond, we’ll retry after 1, 5 and 30 minutes and 2 hours; after 5 failed attempts, notifications will be paused and we’ll email you.

chat-bubble