RecommendAI API Reference
Base URL (production):
https://api.recommendai.io
Base URL (local dev):http://localhost:8080
GraphQL endpoint:/graphql
Content-Type:application/json
Authentication
RecommendAI uses two authentication schemes:
| Scheme | Header | Used For |
|---|---|---|
| API Key | X-API-Key: <key> | Backend-to-backend calls (items, interactions, recommendations) |
| Bearer JWT | Authorization: Bearer <jwt> | Portal / admin routes |
Obtain a JWT via GoTrue:
POST /auth/v1/token?grant_type=password
Content-Type: application/json
{ "email": "admin@tenant.com", "password": "password" }Rate Limits
| Scope | Limit |
|---|---|
| Per API key | 1,000 requests / minute |
| Per IP (unauthenticated) | 60 requests / minute |
| Admin JWT | 200 requests / minute |
HTTP 429 is returned when the limit is exceeded.
Health
GET /health — Public
HTTP/1.1 200 OK
HealthyAuthentication Routes
POST /api/auth/login — Public
Authenticate a user and receive a JWT (dev/internal use; production uses GoTrue).
Request body
{
"email": "user@example.com",
"password": "secure_password"
}Response 200 OK
{
"token": "eyJhbGciOiJIUzI1NiIs...",
"user": {
"id": "user-uuid",
"email": "user@example.com",
"name": "John Doe",
"role": "user",
"isActive": true,
"createdAt": "2025-01-01T00:00:00Z"
}
}POST /api/auth/register — Public
Register a new user.
Request body
{
"email": "newuser@example.com",
"name": "Jane Doe",
"password": "secure_password"
}Response 201 Created — User object without password
Items
Items are the recommendable entities in your catalogue (products, articles, videos, etc.).
GET /api/items — API Key Required
List all items for the tenant.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
pageSize | integer | 20 | Results per page (max 100) |
search | string | — | Full-text search in item metadata |
Response 200 OK
{
"data": [
{
"id": "item-uuid",
"tenantId": "tenant-uuid",
"metadata": {
"title": "Wireless Headphones Pro",
"category": "Electronics",
"price": 149.99,
"rating": 4.8
},
"isActive": true,
"createdAt": "2025-01-01T00:00:00Z",
"updatedAt": "2025-01-15T10:30:00Z"
}
],
"total": 250,
"page": 1,
"pageSize": 20
}GET /api/items/{id} — API Key Required
Get a single item by ID.
Response 200 OK — Full item object
Recommendations (Core Engine)
These endpoints are called from your backend application using an API key. They proxy to the Rust core engine for sub-50ms responses.
POST /api/v1/recommend — API Key Required
Get personalised recommendations for a user.
Request body
{
"userId": "user-abc",
"count": 10,
"algorithm": "hybrid"
}| Field | Type | Required | Description |
|---|---|---|---|
userId | string | ✅ | Your user's unique identifier |
count | integer | ✅ | Number of recommendations (max 100) |
algorithm | string | ❌ | collaborative, content-based, hybrid, deep-learning (default: hybrid) |
Response 200 OK
[
{
"itemId": "item-uuid",
"score": 0.94,
"algorithm": "hybrid",
"explanation": "Based on your interaction history"
},
{
"itemId": "item-uuid-2",
"score": 0.87,
"algorithm": "collaborative",
"explanation": "Users similar to you also liked this"
}
]POST /api/v1/similar — API Key Required
Find items similar to a given item (item-to-item recommendation).
Request body
{
"itemId": "item-uuid",
"count": 5
}Response 200 OK
[
{
"itemId": "similar-item-uuid",
"score": 0.91
}
]POST /api/v1/interactions — API Key Required
Record a user interaction with an item. Send these signals in real time to improve recommendation quality.
Request body
{
"userId": "user-abc",
"itemId": "item-uuid",
"interactionType": "purchase",
"value": 1.0
}interactionType | Weight | Description |
|---|---|---|
view | Low | Item was displayed to user |
click | Medium | User clicked on the item |
like | High | User explicitly liked/saved |
purchase | Highest | User purchased/converted |
value (optional, float 0–1): Custom interaction weight. Defaults to type-based weight.
Response 201 Created
{
"success": true,
"interactionId": "interaction-uuid",
"timestamp": "2025-01-15T10:30:00Z"
}Recommendations (Admin Management)
GET /api/recommendations — Auth Required (Admin)
List all recommendations in the tenant (paginated).
Query parameters: page, pageSize, userId, algorithm
Response 200 OK — Paginated recommendation list
GET /api/recommendations/my — Auth Required
Get the current user's personalised recommendations.
Response 200 OK
{
"data": [
{
"id": "rec-uuid",
"userId": "user-uuid",
"itemId": "item-uuid",
"score": 0.92,
"reason": "Based on your interaction history",
"createdAt": "2025-01-15T10:30:00Z",
"metadata": {
"title": "Wireless Headphones Pro",
"category": "Electronics",
"price": 149.99
}
}
],
"total": 10,
"page": 1,
"pageSize": 10
}GET /api/recommendations/{id} — Auth Required
Get a single recommendation by ID.
DELETE /api/recommendations/{id} — Auth Required (Admin)
Delete a recommendation record.
Response 204 No Content
POST /api/recommendations/generate — Auth Required (Admin)
Trigger a batch recommendation generation job.
Request body
{
"algorithm": "hybrid",
"userSegment": "all",
"count": 10
}Response 202 Accepted
{
"jobId": "gen-job-uuid",
"status": "processing",
"estimatedCompletionMs": 5000
}Users (Admin)
GET /api/users — Auth Required (Admin)
List all users in the tenant (paginated).
Query parameters: page, pageSize, search
Response 200 OK — Paginated user list
GET /api/users/{id} — Auth Required
Get a single user by ID.
Response 200 OK
{
"id": "user-uuid",
"email": "user@example.com",
"name": "John Doe",
"role": "user",
"isActive": true,
"createdAt": "2025-01-01T00:00:00Z",
"lastActiveAt": "2025-01-15T10:00:00Z"
}POST /api/users — Auth Required (Admin)
Create a user.
Request body
{
"email": "user@example.com",
"name": "John Doe",
"role": "user",
"isActive": true
}Response 201 Created — User object
PUT /api/users/{id} — Auth Required (Admin)
Update a user's attributes.
Request body — Same as POST
DELETE /api/users/{id} — Auth Required (Admin)
Permanently delete a user and all associated interactions and recommendations.
Response 204 No Content
PATCH /api/users/{id}/toggle-status — Auth Required (Admin)
Toggle a user's isActive status.
Response 200 OK — Updated user object
Analytics
GET /api/analytics/stats — Auth Required (Admin)
System-wide statistics snapshot.
Response 200 OK
{
"totalUsers": 1250,
"totalItems": 3400,
"totalRecommendations": 45000,
"totalInteractions": 120000,
"activeModels": 8,
"dailyActiveUsers": 340,
"avgAccuracy": 0.87
}GET /api/analytics/data — Auth Required (Admin)
Time-series analytics data.
Query parameters
| Parameter | Values | Default | Description |
|---|---|---|---|
period | 7d, 30d, 90d | 7d | Lookback period |
Response 200 OK
[
{
"date": "2025-01-15",
"totalRecommendations": 520,
"activeUsers": 180,
"accuracy": 0.88
}
]Billing
GET /api/billing/plans — Public
List subscription plans.
Response 200 OK
[
{
"id": "plan-starter",
"name": "Starter",
"monthlyPrice": 49,
"annualPrice": 470,
"requestLimit": 10000,
"itemLimit": 1000,
"userLimit": 500
},
{
"id": "plan-growth",
"name": "Growth",
"monthlyPrice": 149,
"annualPrice": 1430,
"requestLimit": 100000,
"itemLimit": 10000,
"userLimit": 5000
}
]GET /api/billing/current — Auth Required
Get the current tenant's active subscription.
Response 200 OK — Active subscription object
GET /api/billing/usage — Auth Required
Get API usage statistics for the current billing cycle.
Response 200 OK
{
"requestsUsed": 45000,
"requestLimit": 100000,
"percentUsed": 45.0,
"overageUnits": 0,
"overageAmount": 0.0,
"overageBudgetCap": 500,
"budgetExceeded": false,
"itemsUsed": 2340,
"itemsLimit": 10000,
"usersUsed": 850,
"usersLimit": 5000,
"lastRequestAt": "2025-01-15T10:30:45Z"
}POST /api/billing/checkout — Auth Required
Create a Stripe checkout session.
Request body
{
"planId": "plan-growth",
"interval": "monthly"
}Response 200 OK
{
"checkoutUrl": "https://checkout.stripe.com/pay/cs_..."
}POST /api/billing/portal — Auth Required
Create a Stripe customer portal session.
Response 200 OK
{
"portalUrl": "https://billing.stripe.com/session/..."
}GET /api/billing/invoices — Auth Required
Get invoice history for the tenant.
PUT /api/billing/overage-cap — Auth Required
Set the maximum overage budget for the billing cycle.
Request body
{
"capAmount": 250.00
}Response 200 OK — Updated billing settings
GraphQL API
Available at /graphql (same host and port as the REST API).
Queries
# Get recommendations for a user
query GetRecommendations($userId: String!, $count: Int!, $algorithm: String) {
getRecommendations(userId: $userId, count: $count, algorithm: $algorithm) {
itemId
score
algorithm
explanation
}
}
# Find similar items
query GetSimilarItems($itemId: String!, $count: Int!) {
getSimilarItems(itemId: $itemId, count: $count) {
itemId
score
}
}
# API version
query {
getApiVersion
}
# Health check
query {
getHealth {
status
timestamp
}
}Mutations
# Record a user interaction
mutation RecordInteraction(
$userId: String!
$itemId: String!
$interactionType: String!
$value: Float
) {
recordInteraction(
userId: $userId
itemId: $itemId
interactionType: $interactionType
value: $value
) {
success
message
timestamp
}
}Errors
All error responses use RFC 9110 Problem Details format:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "Unauthorized",
"status": 401,
"detail": "API key is missing or invalid",
"traceId": "00-abc123-def456-00"
}| Status | Meaning |
|---|---|
| 400 | Validation error |
| 401 | Missing or invalid API key / JWT |
| 402 | Overage budget cap reached |
| 403 | Insufficient permissions |
| 404 | Resource not found |
| 429 | Rate limit exceeded |
| 500 | Internal error |