Endpoints
Auth Worker
POST /api/auth/register
Create a new user account. No auth required.
Request body:
{ "email": "user@example.com", "password": "min8chars", "name": "João Silva", "phone": "11999999999"}| Field | Type | Required | Rules |
|---|---|---|---|
email | string | ✅ | Valid email |
password | string | ✅ | 8–128 chars |
name | string | ❌ | Trimmed |
phone | string | ❌ | 10–11 digits |
Response 201: { user: { id, email, name, phone } }
- Sets
sessioncookie - Returns
409if email/phone exists
POST /api/auth/login
Authenticate. No auth required.
Request body: { email, password }
Response 200: { user } + session cookie
401wrong credentials403account suspended
POST /api/auth/logout
Destroy session. Requires auth.
Response 200: { message: "Logged out successfully" }
GET /api/auth/me
Current user. Requires auth.
Response 200:
{ "user": { "id": "uuid", "email": "...", "name": "...", "phone": "...", "status": "active", "subscription_status": "active", "subscription_period_end": "2026-07-01T00:00:00.000Z" }}POST /api/auth/password
Change password. Requires auth.
Request body: { oldPassword, newPassword }
Response 200: { message: "Password updated successfully" }
GET /api/users/:id
Public profile. No auth.
Response 200: { user: { id, name, phone } }
Listings Worker
POST /api/listings/upload-image
Upload image to R2. Requires auth.
Request: multipart/form-data, field image
Validation: JPEG/PNG/WebP/GIF, ≤5 MB, 200×200 to 8192×8192 px
Response 200: { url, width, height, size }
- Rate limit: 10 / 60 sec per user
POST /api/listings
Create listing. Requires auth.
Request body:
{ "title": "Casa em Florianópolis", "description": "Ótima casa com 3 quartos", "price": 850000, "property_type": "casa", "city": "Florianópolis", "state_code": "SC", "bedrooms": 3, "bathrooms": 2, "area_m2": 180, "phone": "48999999999", "whatsapp": "48999999999", "images": ["https://{r2}/listings/temp/{userId}/{uuid}.jpg"]}| Field | Required | Rules |
|---|---|---|
title | ✅ | 5–200 chars |
description | ✅ | 10–5000 chars |
price | ✅ | > 0 |
property_type | ✅ | casa, apartamento, terreno, comercial, chacara |
images | ✅ | ≥1 R2 URL |
city, state_code | ❌ | 2-letter UF for state |
bedrooms, bathrooms, area_m2 | ❌ | Integer / positive number |
phone, whatsapp | ❌ | 10–13 digits |
Business rules: 1 free listing per user. Additional listings require subscription → 402 SUBSCRIPTION_REQUIRED.
Response 201: { listing: { ... } }
GET /api/listings
List public listings. No auth.
Query: ?page=1&limit=20 (max 50)
Response 200: { listings, total, page, limit, totalPages }
- Only
status = 'active' - Rate limit: 30 / 60 sec per IP
GET /api/listings/me
My listings. Requires auth.
Response 200: { listings: [...] }
- All statuses, ordered
created_at DESC
GET /api/listings/user/:id
User’s public listings. No auth.
Query: ?page=1&limit=20
Response 200: Paginated, only status = 'active'
GET /api/listings/:id
Single listing.
Response 200: { listing: { ... } }
- Hidden listings require auth + ownership
PUT /api/listings/:id
Update listing. Requires auth + ownership.
Request body: Partial update, all fields optional. May include status: active, sold, pending, paused.
Response 200: Updated listing
- Rate limit: 10 / 60 sec per user
DELETE /api/listings/:id
Delete listing. Requires auth + ownership.
Response 200: { message: "Anúncio excluído com sucesso" }
- Also deletes R2 images
Corretores Worker
POST /api/corretores
Register as agent. No auth.
Request body:
{ "name": "Maria Souza", "email": "maria@corretora.com", "whatsapp": "11999999999", "creci_estado": "SP", "creci_numero": "123456", "cidade": "São Paulo", "estado": "SP", "especializacao": "Imóveis Residenciais"}| Field | Required | Rules |
|---|---|---|
name | ✅ | 2–200 chars |
email | ✅ | Valid email |
whatsapp | ✅ | 10–13 digits |
creci_estado | ✅ | 2-letter UF |
creci_numero | ✅ | Max 20 chars |
cidade | ✅ | Max 200 chars |
estado | ✅ | 2-letter UF |
especializacao | ❌ | See enum below |
mensagem | ❌ | Max 2000 chars |
Especialização values: Imóveis Residenciais, Imóveis Comerciais, Imóveis de Luxo, Loteamentos e Terrenos, Imóveis para Temporada, Investimentos Imobiliários, Primeiro Imóvel, Corporativo, Outro
Response 201: { id, message: "Cadastro recebido com sucesso!..." }
- Status stored as
pending - Rate limits: 5 / 15 min per IP; 3 / 15 min per email
GET /api/corretores
List approved agents. No auth.
Query: ?state=SP&city=São+Paulo&limit=50&offset=0
Response 200: { agents: [...] }
- Only
status = 'approved' - Max limit 100
GET /api/corretores/:id
Single approved agent. No auth.
Response 200: { agent: { ... } }
404if not found or not approved
PUT /api/corretores/:id
Update own profile. Requires auth + ownership.
Request body: Partial update. Extra fields: bio, notes, profile_image.
Response 200: { message: "Cadastro atualizado com sucesso" }
DELETE /api/corretores/:id
Delete own profile. Requires auth + ownership.
Response 204
Billing Worker
All require auth except webhook.
POST /api/billing/checkout
Create Stripe checkout session.
Response 200: { url: "https://checkout.stripe.com/..." }
POST /api/billing/portal
Open Stripe customer portal.
Response 200: { url: "https://billing.stripe.com/..." }
404if nostripe_customer_id
GET /api/billing/status
Subscription status.
Response 200: { subscribed, status, periodEnd }
POST /api/billing/webhook
Stripe webhook. No auth.
Headers: Stripe-Signature
Handled events:
| Event | Action |
|---|---|
checkout.session.completed | subscription_status = 'active' |
invoice.payment_succeeded | Extend subscription_period_end |
invoice.payment_failed | subscription_status = 'past_due' |
customer.subscription.deleted | subscription_status = 'inactive' |
Response 200: { received: true }
Chat Worker
Chat
| Method | Path | Auth | Description |
|---|---|---|---|
GET | /api/ws?roomId=xxx | — | WebSocket upgrade |
GET | /api/chat/rooms | — | List rooms |
POST | /api/chat/rooms | — | Create/update room |
GET | /api/chat/history?roomId=xxx | — | Message history |
Search
| Method | Path | Auth | Description |
|---|---|---|---|
GET | /api/search?q=... | — | Site-wide search |
GET | /api/bucket-search | — | R2 object search |
GET | /api/page-content?url=/path | — | Page content extraction |
GET | /api/search/categories | — | List categories |
Admin
All require X-Admin-Token header.
| Method | Path | Description |
|---|---|---|
POST | /api/admin/login | Admin login |
POST | /api/admin/logout | Invalidate session |
GET | /api/admin/stats | Dashboard stats |
GET | /api/admin/users | List users |
GET | /api/admin/listings | List listings |
GET | /api/admin/rooms | List chat rooms |
GET | /api/admin/messages | List messages |