API Reference
Complete endpoint documentation for Miata Maestro
Base Information
Base URL:
http://localhost:3000
Authentication: Session-based (cookies)
Content Types: application/json, application/x-www-form-urlencoded
Authentication
POST
/login
Authenticate with Facebook credentials and create session
Request Body
Content-Type: application/x-www-form-urlencoded
email=user@example.com&password=userpassword
Parameters
Parameter
Type
Description
email
string
Facebook email address
password
string
Facebook password
Response
HTTP/1.1 302 Found
Location: /search
Set-Cookie: connect.sid=s%3A...; Path=/; HttpOnly
POST
/logout
Destroy session and logout
Response
HTTP/1.1 302 Found
Location: /
Page Endpoints
GET
/
Login page (redirects to /search if authenticated)
GET
/search
Search configuration page
Authentication
Requires active session. Redirects to / if not logged in.
GET
/test
System status and health check page
Scraping
POST
/scrape
Initialize scraping session with search parameters
Request Body
Content-Type: application/x-www-form-urlencoded
zip=90210&radius=50&yearMin=1990&yearMax=1997&maxMileage=100000&limit=20&provider=ollama&ollamaPort=11434
Parameters
Parameter
Type
Description
zip
string
ZIP code for search center
radius
number
Search radius in miles (1-500)
yearMin
number
Minimum year (1989-1997)
yearMax
number
Maximum year (1989-1997)
maxMileage
number
Maximum mileage threshold
maxPrice
number
Optional maximum price limit
limit
number
Number of listings to process (1-100)
headless
boolean
Browser visibility (true/false)
provider
string
AI provider ("ollama" or "gpt-oss")
ollamaPort
number
Ollama service port (default: 11434)
Response
HTTP/1.1 200 OK
Content-Type: text/html
<!-- Search progress page with loading animation -->
GET
/scrape-results
Execute scraping and display results
Query Parameters
Parameter
Type
Description
debug
boolean
Enable debug mode (processes only 3 listings)
Response
HTTP/1.1 200 OK
Content-Type: text/html
<!-- Results page with listing cards -->
Real-time Updates
GET
/progress
Server-Sent Events stream for real-time progress updates
Headers
Accept: text/event-stream
Cache-Control: no-cache
Response
HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
data: {"step":"initializing","details":"Setting up scraping session...","timestamp":"2024-01-15T10:30:00.000Z"}
data: {"step":"browser_start","details":"Starting browser...","timestamp":"2024-01-15T10:30:01.000Z"}
data: {"step":"logging_in","details":"Navigating to Facebook login...","timestamp":"2024-01-15T10:30:02.000Z"}
Progress Steps
initializing: Setting up scraping session
browser_start: Starting Puppeteer browser
logging_in: Facebook authentication
navigating: Navigating to Marketplace
searching: Finding listings
extracting: Processing individual listings
complete: Scraping finished
AI Evaluation
POST
/evaluate-listing
Get AI analysis for a specific listing
Request Body
Content-Type: application/json
{
"listingId": "listing_1234567890_0"
}
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"evaluation": "<strong>Pros:</strong>\n⢠Clean title\n⢠Low mileage for year\n⢠Manual transmission\n\n<strong>Concerns:</strong>\n⢠Some rust visible in photos\n⢠No maintenance records provided\n\n<strong>Accurate Price:</strong> $4,500\n\n<strong>Lowball:</strong> $3,800"
}
Error Response
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": "Listing listing_1234567890_0 not found"
}
POST
/generate-lowball
Generate casual lowball message for negotiation
Request Body
Content-Type: application/json
{
"listingId": "listing_1234567890_0"
}
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"message": "hey! saw your miata listing, looks pretty good but noticed some rust spots and the paint could use work... would you consider $3800? can pick up this weekend đ"
}
Data Models
Listing Object
{
"id": "listing_1705315200000_0",
"title": "1995 Mazda Miata - Clean Title",
"price": 5000,
"year": 1995,
"mileage": 80000,
"transmission": "Manual",
"description": "Well-maintained NA Miata with clean title. Recent timing belt service...",
"url": "https://www.facebook.com/marketplace/item/1234567890",
"images": [
"https://scontent.xx.fbcdn.net/v/t45.5328-4/...",
"https://scontent.xx.fbcdn.net/v/t45.5328-4/..."
],
"rawText": "",
"lowballPrice": 3800
}
Field Descriptions
id: Unique identifier generated from timestamp and index
title: Listing title from Facebook Marketplace
price: Asking price in USD (integer)
year: Vehicle year (1989-1997 for NA Miata)
mileage: Odometer reading in miles (integer)
transmission: "Manual", "Automatic", or null
description: Listing description (truncated to 500 chars)
url: Direct link to Facebook Marketplace listing
images: Array of image URLs (up to 2 for performance)
lowballPrice: AI-calculated lowball offer (added after evaluation)
Progress Update Object
{
"step": "extracting",
"details": "Processing listing 5/20...",
"timestamp": "2024-01-15T10:30:00.000Z"
}
Error Codes
401 Unauthorized
Session required but not authenticated
Login via POST /login
404 Not Found
Listing ID not found in session
Ensure listing was scraped in current session
400 Bad Request
Missing or invalid parameters
Check parameter requirements
500 Internal Server Error
Scraping, AI, or browser automation failed
Check console logs, enable debug mode
Rate Limits & Best Practices
⥠Performance Guidelines
Concurrent Sessions: Limit to 1 scraping session at a time
Request Frequency: Wait for previous scrape to complete
Result Limits: Start with 10-20 listings for testing
AI Evaluations: Process individually, not in batch
đ Security Considerations
Session Security: Sessions expire after 24 hours
Credential Storage: Only in server memory, never persisted
CORS: API restricted to same-origin requests
Facebook TOS: Respect platform terms of service