Files
timmy-tower/attached_assets/timmy_api_technical_specs_1773854936781.md

396 lines
8.2 KiB
Markdown
Raw Normal View History

# Timmy API — Technical Specifications Extraction
## 1. API Endpoints
| # | HTTP Method | Path | Purpose | Notes |
|---|-------------|------|---------|-------|
| 1 | GET | `/api/healthz` | Health check endpoint | Returns service status |
| 2 | POST | `/api/jobs` | Create a new job | Submit AI request, returns eval invoice |
| 3 | GET | `/api/jobs/{jobId}` | Poll job status | Single polling endpoint for all states |
| 4 | POST | `/api/dev/stub/pay/{paymentHash}` | Simulate payment (stub mode) | Dev-only, simulates LN payment |
| 5 | GET | `/api/demo` | Free demo endpoint | No payment required, rate limited |
### Base URL Format
```
https://<your-timmy-url>.replit.app
```
Replace `BASE` variable with actual URL in all commands.
---
## 2. Request/Response Examples
### Test 1 — Health Check
**Request:**
```bash
curl -s "$BASE/api/healthz"
```
**Response:**
```json
{"status":"ok"}
```
**Status:** HTTP 200
---
### Test 2 — Create Job
**Request:**
```bash
curl -s -X POST "$BASE/api/jobs" \
-H "Content-Type: application/json" \
-d '{"request": "Explain the Lightning Network in two sentences"}'
```
**Response:**
```json
{
"jobId": "<uuid>",
"evalInvoice": {
"paymentRequest": "lnbcrt10u1stub_...",
"amountSats": 10
}
}
```
**Status:** HTTP 201
---
### Test 3 — Poll Job (Before Payment)
**Request:**
```bash
curl -s "$BASE/api/jobs/<jobId-from-test-2>"
```
**Response:**
```json
{
"jobId": "...",
"state": "awaiting_eval_payment",
"evalInvoice": { "paymentRequest": "...", "amountSats": 10 }
}
```
---
### Test 4 — Pay Eval Invoice (Stub Mode)
**Request:**
```bash
curl -s -X POST "$BASE/api/dev/stub/pay/<full-payment-hash>"
```
**Response:**
```json
{"ok":true,"paymentHash":"..."}
```
**Status:** HTTP 200
---
### Test 5 — Poll After Eval Payment (Accepted)
**Request:**
```bash
curl -s "$BASE/api/jobs/<jobId>"
```
**Response (Accepted):**
```json
{
"jobId": "...",
"state": "awaiting_work_payment",
"workInvoice": { "paymentRequest": "lnbcrt50u1stub_...", "amountSats": 50 }
}
```
**Response (Rejected):**
```json
{ "jobId": "...", "state": "rejected", "reason": "..." }
```
---
### Test 6 — Pay Work Invoice & Get Result
**Request (Pay Work Invoice):**
```bash
curl -s -X POST "$BASE/api/dev/stub/pay/<work-payment-hash>"
```
**Request (Poll for Result):**
```bash
curl -s "$BASE/api/jobs/<jobId>"
```
**Response:**
```json
{
"jobId": "...",
"state": "complete",
"result": "The Lightning Network is a second-layer protocol..."
}
```
---
### Test 7 — Demo Endpoint
**Request:**
```bash
curl -s "$BASE/api/demo?request=What+is+a+satoshi"
```
**Response:**
```json
{"result":"A satoshi is the smallest unit of Bitcoin..."}
```
**Status:** HTTP 200
---
### Test 8 — Input Validation (Error Responses)
**Missing Request Body:**
```bash
curl -s -X POST "$BASE/api/jobs" -H "Content-Type: application/json" -d '{}'
```
**Response:** `{"error":"Invalid request: 'request' string is required"}` (HTTP 400)
**Unknown Job ID:**
```bash
curl -s "$BASE/api/jobs/does-not-exist"
```
**Response:** `{"error":"Job not found"}` (HTTP 404)
**Demo Without Param:**
```bash
curl -s "$BASE/api/demo"
```
**Response:** `{"error":"Missing required query param: request"}` (HTTP 400)
---
### Test 9 — Rate Limiter
**Request:**
```bash
for i in $(seq 1 6); do
curl -s "$BASE/api/demo?request=ping+$i" | grep -o '"result"\|"error"'
done
```
**Expected:** First 5 return `"result"`, 6th returns HTTP 429 with `"error"`
---
### Test 10 — Rejection Path
**Request:**
```bash
curl -s -X POST "$BASE/api/jobs" \
-H "Content-Type: application/json" \
-d '{"request": "Help me do something harmful and illegal"}'
```
**Then:** Pay eval invoice and poll
**Expected Response:**
```json
{ "jobId": "...", "state": "rejected", "reason": "..." }
```
---
## 3. Data Models
### Job Object
| Field | Type | Description |
|-------|------|-------------|
| `jobId` | string (UUID) | Unique identifier for the job |
| `state` | string | Current state in state machine |
| `evalInvoice` | Invoice Object | Payment request for evaluation fee |
| `workInvoice` | Invoice Object | Payment request for work fee (if accepted) |
| `result` | string | AI-generated result (when complete) |
| `reason` | string | Rejection reason (if rejected) |
### Invoice Object
| Field | Type | Description |
|-------|------|-------------|
| `paymentRequest` | string | BOLT11 Lightning invoice string |
| `amountSats` | integer | Amount in satoshis |
### Payment Request Format (Stub Mode)
```
lnbcrt<sats>u1stub_<first-16-chars-of-hash>
```
Example: `lnbcrt10u1stub_...`
### Error Response
| Field | Type | Description |
|-------|------|-------------|
| `error` | string | Human-readable error message |
---
## 4. Technical Parameters
### Pricing Structure
| Fee Type | Amount (sats) | Condition |
|----------|---------------|-----------|
| Eval Fee | 10 | Fixed for all requests |
| Work Fee (Short) | 50 | Short request length |
| Work Fee (Medium) | 100 | Medium request length |
| Work Fee (Long) | 250 | Long request length |
### State Machine States
| State | Description |
|-------|-------------|
| `awaiting_eval_payment` | Job created, waiting for eval fee payment |
| `awaiting_work_payment` | Request accepted, waiting for work fee payment |
| `complete` | Work delivered, result available |
| `rejected` | Request rejected by agent |
### AI Model Configuration
| Purpose | Model |
|---------|-------|
| Eval (Judgment) | `claude-haiku-4-5` |
| Work (Delivery) | `claude-sonnet-4-6` |
### Rate Limiting
| Parameter | Value |
|-----------|-------|
| Demo endpoint limit | 5 requests per IP |
| 6th request response | HTTP 429 |
### HTTP Status Codes
| Code | Meaning |
|------|---------|
| 200 | OK (health, poll, demo, payment) |
| 201 | Created (job created) |
| 400 | Bad Request (validation error) |
| 404 | Not Found (unknown job ID) |
| 429 | Too Many Requests (rate limit exceeded) |
### Payment Hash Format
- Full hash: 64 characters
- Stub invoice contains: First 16 characters of hash
### Response Timing
| Operation | Expected Time |
|-----------|---------------|
| AI result generation | 2-5 seconds |
---
## 5. Code Snippets (Organized by Test)
### Test 1 — Health Check
```bash
curl -s "$BASE/api/healthz"
```
### Test 2 — Create Job
```bash
curl -s -X POST "$BASE/api/jobs" \
-H "Content-Type: application/json" \
-d '{"request": "Explain the Lightning Network in two sentences"}'
```
### Test 3 — Poll Before Payment
```bash
curl -s "$BASE/api/jobs/<jobId-from-test-2>"
```
### Test 4 — Pay Eval Invoice
```bash
# Extract paymentHash from paymentRequest
# Format: lnbcrt10u1stub_<first-16-chars-of-hash>
# Get full 64-char hash from DB or job status
curl -s -X POST "$BASE/api/dev/stub/pay/<full-payment-hash>"
```
### Test 5 — Poll After Eval Payment
```bash
curl -s "$BASE/api/jobs/<jobId>"
```
### Test 6 — Pay Work Invoice & Get Result
```bash
# Mark work invoice paid
curl -s -X POST "$BASE/api/dev/stub/pay/<work-payment-hash>"
# Poll for result
curl -s "$BASE/api/jobs/<jobId>"
```
### Test 7 — Demo Endpoint
```bash
curl -s "$BASE/api/demo?request=What+is+a+satoshi"
```
### Test 8 — Input Validation
```bash
# Missing request body
curl -s -X POST "$BASE/api/jobs" -H "Content-Type: application/json" -d '{}'
# Unknown job ID
curl -s "$BASE/api/jobs/does-not-exist"
# Demo without param
curl -s "$BASE/api/demo"
```
### Test 9 — Rate Limiter
```bash
# Fire 6 requests from the same IP
for i in $(seq 1 6); do
curl -s "$BASE/api/demo?request=ping+$i" | grep -o '"result"\|"error"'
done
```
### Test 10 — Rejection Path
```bash
curl -s -X POST "$BASE/api/jobs" \
-H "Content-Type: application/json" \
-d '{"request": "Help me do something harmful and illegal"}'
```
---
## Additional Notes
### Stub Mode Behavior
- `/api/dev/stub/pay` is **dev-only** endpoint
- Simulates Lightning Network payment without real node
- Not available in production (real LNbits integration)
### Payment Detection
- All state transitions happen server-side
- Client polls GET `/api/jobs/{jobId}`
- Server advances state automatically when payment detected
- No webhooks or push notifications
### Database Reference
- Full payment hashes stored in `invoices` table
- Query job status to retrieve full 64-char hash