Custom Integration: Local API
SpamFoo runs a local HTTP API on port 16253 that accepts email for classification and returns results as JSON. This is the primary integration method for mail servers and custom applications that need real-time classification.
Basics
- Base URL:
http://localhost:16253 - Authentication: None required (local-only service)
- Content types: JSON for file-path requests, raw RFC 5322 for stream requests
- Response format: JSON
Classifying Email
There are two ways to send an email for classification: by file path or by streaming the raw message content. Both return the same response format.
By File Path
Use this when SpamFoo has filesystem access to the .eml file.
POST /classify
Content-Type: application/json
{
"path": "/var/spool/mail/message.eml",
"ipAddress": "203.0.113.50",
"senderEmail": "sender@example.com",
"userId": "user@domain.com"
}
The path field is required. All other fields are optional but improve classification accuracy and enable per-user personalization.
By Stream
Use this when SpamFoo does not have access to the file, or when you want to avoid writing to disk. Send the raw email content as the request body and pass metadata in headers.
POST /classify-stream
Content-Type: message/rfc822
X-Sender-IP: 203.0.113.50
X-Sender-Email: sender@example.com
X-User-ID: user@domain.com
[raw .eml content]
All headers are optional. Messages up to 10 MB are buffered in memory; larger messages are written to a temporary file automatically.
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"isSpam": false,
"spamProbability": 0.12,
"classification": "primary",
"textSpamScore": 0.08,
"metaSpamScore": 0.15,
"confidenceMargin": 0.76,
"entropy": 0.4,
"shouldEscalate": false
}
| Field | Type | Description |
|---|---|---|
isSpam |
boolean | Whether SpamFoo considers the message spam |
spamProbability |
float | Spam confidence from 0.0 (definitely not spam) to 1.0 (definitely spam) |
classification |
string | Message class: primary, promotions, updates, or
transactions |
textSpamScore |
float | Score from the text analysis model |
metaSpamScore |
float | Score from the metadata/header analysis model |
confidenceMargin |
float | How far the score is from the decision boundary (higher = more confident) |
shouldEscalate |
boolean | True if SpamFoo recommends human review (low confidence or conflicting signals) |
bypassReason |
string or null | If classification was overridden by a rule, indicates the reason (e.g., user_rule, knn_memory) |
Error Responses
| Status | Meaning |
|---|---|
400 |
Bad request (missing path, file not found, or invalid email content) |
503 |
Queue timeout. SpamFoo is overloaded and could not process the request in time. Deliver the email without classification and try again later. |
Tabs-Only Classification
If you handle spam detection separately and only need message classification, use the tabs endpoints. These skip spam scoring and only return a message class.
POST /tabs/classify
POST /tabs/classify-stream
Request format is the same as the classification endpoints above. The response includes:
{
"classification": "promotions",
"confidence": 0.92,
"classificationProbabilities": {
"primary": 0.05,
"promotions": 0.92,
"updates": 0.02,
"transactions": 0.01
},
"elapsedMs": 18
}
Diagnostic Classification
For debugging or testing, the diagnostic endpoints return a full breakdown of how SpamFoo reached its decision, including per-model scores, signal extraction details, and timing.
POST /classify/diagnostic
POST /classify/diagnostic-stream
Request format is the same as the regular classification endpoints. The response is significantly larger and includes model-by-model analysis. Use this for troubleshooting, not in production mail flow.
Submitting Feedback
When a user corrects a misclassification (marks spam as not spam or vice versa), send the correction to SpamFoo so it can learn from the mistake.
/feedback, /tabs/feedback) are not available yet. Use the -stream variants to submit corrections by streaming the raw message content.
Spam/Ham Corrections
POST /feedback
Content-Type: application/json
{
"path": "/var/spool/mail/message.eml",
"userId": "user@domain.com",
"isSpam": true,
"senderEmail": "sender@example.com"
}
Or by stream:
POST /feedback-stream
X-User-ID: user@domain.com
X-Is-Spam: true
X-Sender-Email: sender@example.com
[raw .eml content]
Tab Corrections
POST /tabs/feedback
Content-Type: application/json
{
"path": "/var/spool/mail/message.eml",
"userId": "user@domain.com",
"correctClassification": "updates"
}
Or by stream:
POST /tabs/feedback-stream
X-User-ID: user@domain.com
X-Classification: updates
[raw .eml content]
See Feedback and Training for more on how corrections improve classification.
Health Check
GET /health
Returns the service status, queue depth, and active request counts. Use this for monitoring and load balancing. Returns 200 when healthy.
{
"status": "healthy",
"activeRequests": 1,
"spoolQueue": {
"active": 1,
"waiting": 0,
"maxConcurrency": 2
}
}
Next Steps
- See the API Reference for the complete endpoint listing
- Review Configuration to tune concurrency and timeouts for your workload
- Set up health monitoring for production deployments