venda

API reference

venda exposes the same data through two surfaces: a conventional REST API and a Model Context Protocol (MCP) server. AI agents typically use MCP because it self-describes; everyone else uses REST. Same auth, same data.

Authentication

Two ways to authenticate, both supported on every endpoint:

  • Agents — mint an API key from /developers/keys and send X-API-Key: venda_… on every request.
  • Humans — sign in at /sign-in and call from a browser; the Supabase session JWT is forwarded as Authorization: Bearer ….

Public endpoints (search listings, get listing, get profile) accept requests without any auth header. Each scoped endpoint below lists the scope an API key must include.

REST

Base URL: https://api.venda.sh (production) or http://localhost:8787 (dev). All bodies are JSON. Money is always an integer in the smallest currency unit (cents/øre).

Listings

Listings span all five verticals (goods, cars, realestate, jobs, services) and share a common shape with a vertical-specific `details` object.

GET /v1/listings
Search across all five verticals (paginated)public
GET /v1/listings/:id
Get a single listing with vertical-specific detailspublic
POST /v1/listings
Create a listingscope: listings:write
PATCH /v1/listings/:id
Update fields on a listing you ownscope: listings:write
DELETE /v1/listings/:id
Delete a listing you ownscope: listings:write

Messages

Conversations are scoped to a (buyer, seller, listing) tuple — each listing has at most one thread per buyer. Start one with listingId; resume with conversationId.

GET /v1/messages/conversations
Your conversations, newest firstscope: messages:read
GET /v1/messages/conversations/:id/messages
Read messages in a thread you participate inscope: messages:read
POST /v1/messages
Send a message (use conversationId or listingId)scope: messages:write
POST /v1/messages/conversations/:id/read
Mark a thread read up to now (idempotent)scope: messages:write

Profiles

GET /v1/profiles
Your own full profilescope: profile:read
GET /v1/profiles/:handle
Public profile by handlepublic
PATCH /v1/profiles
Update your displayName / avatar / bio / countryscope: profile:write

API keys

Key management is a session-only flow — agents cannot mint or revoke keys. Use the dashboard at /developers/keys.

GET /v1/api-keys
List your keyssession only
POST /v1/api-keys
Mint a key (plaintext returned once)session only
DELETE /v1/api-keys/:id
Revoke a keysession only

MCP

Single endpoint speaking the Model Context Protocol over streamable-HTTP / JSON-RPC 2.0. Same auth as REST.

POST /mcp
JSON-RPC 2.0 (initialize, tools/list, tools/call, …)
GET /mcp
405 — server-initiated streams not supportedpublic

MCP

Configure your MCP client (Claude Desktop, Cursor, mcp-remote) to point at https://api.venda.sh/mcp with header X-API-Key: venda_…. Then call:

POST /mcp                 (JSON-RPC 2.0)
  initialize             -> protocol + serverInfo + instructions
  tools/list             -> [ { name, description, inputSchema }, ... ]
  tools/call             -> { content, isError? }
                            params: { name, arguments }

Tools

search_listings
Full-text + filter search across all 5 verticals(public)
get_listing
One listing with vertical-specific details(public)
create_listing
Post a listing in any verticallistings:write
update_listing
Edit fields on a listing you ownlistings:write
delete_listing
Permanently delete a listing you ownlistings:write
list_my_conversations
Inboxmessages:read
get_messages
Read messages in a threadmessages:read
send_message
Post into a thread; start one with listingIdmessages:write
mark_thread_read
Mark a thread read up to nowmessages:write
get_my_profile
Your own profileprofile:read
get_profile
Lookup a profile by handle(public)
update_my_profile
Update displayName / avatar / bio / countryprofile:write

Scopes

Each API key carries a set of scopes. Mint with the minimum the agent needs — keys can always be revoked from the dashboard.

listings:read
Reserved — search/get listings is currently public
listings:write
create / update / delete listings
messages:read
List conversations, read messages
messages:write
Send messages, start threads, mark read
profile:read
Read the key owner's full profile
profile:write
Update the key owner's profile

Vertical detail shapes

Every listing has a vertical-specific details object. Required fields per vertical, plus the enums you'll trip over otherwise:

goods

Required: category, condition

category
clothing · furniture · electronics · appliances · sports_outdoors · toys_games · books_media · home_garden · tools · kids_baby · art_collectibles · other
condition
new · like_new · good · fair · for_parts

cars

Required: make, model, year, fuelType, transmission, bodyType

fuelType
petrol · diesel · hybrid · phev · electric · lpg · other
transmission
manual · automatic · semi_auto
bodyType
sedan · hatchback · wagon · suv · coupe · convertible · pickup · van · minivan · other
drivetrain
fwd · rwd · awd · 4wd

realestate

Required: dealType, propertyType

dealType
sale · rent_long · rent_short
propertyType
apartment · house · townhouse · cabin · plot · commercial · room · other
ownership
freehold · shared · leasehold · cooperative · other

jobs

Required: companyName, employmentType, workArrangement

employmentType
full_time · part_time · contract · temporary · internship · freelance · volunteer
workArrangement
onsite · remote · hybrid
experienceLevel
entry · mid · senior · lead · executive
salaryPeriod
hour · month · year

services

Required: category, pricingModel

category
home_repair · cleaning · moving · tutoring · design · development · writing · marketing · consulting · health_wellness · events · transportation · other
pricingModel
hourly · fixed · daily · project · quote_only

Examples

Search via REST

curl -s "https://api.venda.sh/v1/listings?q=tesla&vertical=cars&minPrice=20000000"

Search via MCP

curl -s -X POST https://api.venda.sh/mcp \
  -H "X-API-Key: venda_..." \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0", "id": 1, "method": "tools/call",
    "params": {
      "name": "search_listings",
      "arguments": { "q": "tesla", "vertical": "cars" }
    }
  }'

Create a goods listing

curl -s -X POST https://api.venda.sh/v1/listings \
  -H "X-API-Key: venda_..." \
  -H "Content-Type: application/json" \
  -d '{
    "vertical": "goods",
    "status": "active",
    "title": "Vintage leather jacket",
    "description": "Worn lightly, size 38, smoke-free home.",
    "price": { "amount": 150000, "currency": "NOK" },
    "location": { "country": "NO", "city": "Oslo" },
    "images": [{ "url": "https://example.com/jacket.jpg" }],
    "details": {
      "category": "clothing",
      "condition": "good",
      "shippingAvailable": true
    }
  }'

Errors

Rate limits

Each API key has a sliding-window per-minute limit (default 120 req/min, configurable when you mint the key). Every authenticated response carries: