Skip to main content

Client API Endpoints

The Client API provides authenticated endpoints for registered users to manage their submitted items, view dashboard statistics, and access geographic data. All endpoints require session-based authentication via requireClientAuth().

Source directory: template/app/api/client/


Authentication

Every endpoint in this group requires a valid user session. Unauthenticated requests receive:

Status 401

{
"success": false,
"error": "Unauthorized. Please sign in to continue."
}

Dashboard Statistics

Get Dashboard Stats

Returns comprehensive dashboard statistics for the authenticated user.

PropertyValue
MethodGET
Path/api/client/dashboard/stats
AuthSession (user)
Sourceclient/dashboard/stats/route.ts

Response

Status 200

{
"success": true,
"totalSubmissions": 23,
"totalViews": 0,
"totalVotesReceived": 156,
"totalCommentsReceived": 89,
"viewsAvailable": false,
"recentActivity": {
"newSubmissions": 3,
"newViews": 0
},
"uniqueItemsInteracted": 45,
"totalActivity": 237,
"activityChartData": [
{ "date": "Mon", "submissions": 1, "views": 0, "engagement": 5 }
],
"engagementChartData": [
{ "name": "Votes", "value": 156, "color": "#8884d8" }
],
"submissionTimeline": [
{ "month": "Mar", "submissions": 5 }
],
"engagementOverview": [
{ "week": "W1", "votes": 10, "comments": 3 }
],
"statusBreakdown": [
{ "status": "Approved", "value": 15, "color": "#22c55e" },
{ "status": "Pending", "value": 5, "color": "#f59e0b" },
{ "status": "Rejected", "value": 3, "color": "#ef4444" }
],
"topItems": [
{ "id": "item_1", "title": "My Tool", "views": 100, "votes": 25, "comments": 8 }
]
}

curl Example

curl -s http://localhost:3000/api/client/dashboard/stats \
-H "Cookie: next-auth.session-token=<session_token>"

Get Geographic Stats

Returns geographic coverage statistics for the authenticated user's items.

PropertyValue
MethodGET
Path/api/client/geo-stats
AuthSession (user)
Sourceclient/geo-stats/route.ts

Response

Status 200

{
"success": true,
"total_items": 10,
"items_with_location": 7,
"items_remote": 2,
"service_area_breakdown": [
{ "area": "local", "count": 3 },
{ "area": "regional", "count": 2 }
],
"top_cities": [
{ "city": "New York", "count": 3 }
],
"top_countries": [
{ "country": "United States", "count": 5 }
]
}

curl Example

curl -s http://localhost:3000/api/client/geo-stats \
-H "Cookie: next-auth.session-token=<session_token>"

Get Item Coordinates

Returns coordinates for all user items that have location data, suitable for map rendering.

PropertyValue
MethodGET
Path/api/client/items/coordinates
AuthSession (user)
Sourceclient/items/coordinates/route.ts

Response

Status 200

{
"success": true,
"coordinates": [
{
"slug": "my-item",
"name": "My Item",
"latitude": 40.7128,
"longitude": -74.006
}
]
}

curl Example

curl -s http://localhost:3000/api/client/items/coordinates \
-H "Cookie: next-auth.session-token=<session_token>"

Items Management

List User Items

Returns a paginated list of items submitted by the authenticated user.

PropertyValue
MethodGET
Path/api/client/items
AuthSession (user)
Sourceclient/items/route.ts

Query Parameters

ParameterTypeRequiredDefaultDescription
pageintegerNo1Page number (min: 1)
limitintegerNo10Items per page (1-100)
statusstringNo--Filter: all, pending, approved, rejected
searchstringNo--Search by item name or description
sortBystringNo--Sort field
sortOrderstringNo--Sort direction
deletedbooleanNofalseIf true, returns soft-deleted items

Response

Status 200

{
"success": true,
"items": [ /* item objects */ ],
"total": 23,
"page": 1,
"limit": 10,
"totalPages": 3,
"stats": {
"total": 20,
"pending": 3,
"approved": 15,
"rejected": 2,
"deleted": 1
}
}

curl Example

# List approved items, page 2
curl -s "http://localhost:3000/api/client/items?status=approved&page=2&limit=10" \
-H "Cookie: next-auth.session-token=<session_token>"

# Search for items
curl -s "http://localhost:3000/api/client/items?search=productivity" \
-H "Cookie: next-auth.session-token=<session_token>"

# List deleted items
curl -s "http://localhost:3000/api/client/items?deleted=true" \
-H "Cookie: next-auth.session-token=<session_token>"

Create Item

Creates a new item submission. The item is set to pending status for admin review.

PropertyValue
MethodPOST
Path/api/client/items
AuthSession (user)
Sourceclient/items/route.ts

Request Body

{
"name": "Awesome Tool",
"description": "A great productivity tool that helps teams collaborate.",
"source_url": "https://example.com",
"category": "Productivity",
"tags": ["collaboration", "remote-work"],
"icon_url": "https://example.com/icon.png"
}
FieldTypeRequiredDescription
namestringYesItem name (3-100 characters)
descriptionstringYesItem description (10-500 characters)
source_urlstring (URI)YesMain URL/link for the item
categorystring | string[]NoCategory name or array of categories
tagsstring[]NoArray of tag strings
icon_urlstring (URI)NoURL to item icon

Response

Status 201

{
"success": true,
"item": { /* created item object */ },
"message": "Item submitted successfully. It will be reviewed by our team before being published."
}

Status 400 -- Validation error

{
"success": false,
"error": "Name must be at least 3 characters"
}

curl Example

curl -s -X POST http://localhost:3000/api/client/items \
-H "Content-Type: application/json" \
-H "Cookie: next-auth.session-token=<session_token>" \
-d '{
"name": "Awesome Tool",
"description": "A great productivity tool that helps teams collaborate effectively.",
"source_url": "https://example.com",
"category": "Productivity",
"tags": ["collaboration"]
}'

Get Single Item

Returns details of a specific item owned by the authenticated user.

PropertyValue
MethodGET
Path/api/client/items/{id}
AuthSession (user, owner)
Sourceclient/items/[id]/route.ts

Path Parameters

ParameterTypeDescription
idstringItem ID

Response

Status 200

{
"success": true,
"item": { /* item object */ },
"engagement": {
"views": 150,
"likes": 23
}
}
StatusDescription
400Invalid item ID
401Unauthorized
403Not the item owner
404Item not found

Update Item

Updates an item owned by the authenticated user. If the item was previously approved, updating it changes its status to pending for re-review.

PropertyValue
MethodPUT
Path/api/client/items/{id}
AuthSession (user, owner)
Sourceclient/items/[id]/route.ts

Request Body

All fields are optional. At least one field must be provided.

{
"name": "Updated Tool Name",
"description": "Updated description with more details.",
"source_url": "https://example.com/v2",
"category": ["Productivity", "Developer Tools"],
"tags": ["collaboration", "ai"],
"icon_url": "https://example.com/new-icon.png"
}

Response

Status 200

{
"success": true,
"item": { /* updated item object */ },
"statusChanged": true,
"previousStatus": "approved",
"message": "Item updated successfully. Since it was previously approved, it has been moved to pending for re-review."
}
FieldTypeDescription
statusChangedbooleantrue if status changed from approved to pending
previousStatusstringThe item's status before the update

curl Example

curl -s -X PUT http://localhost:3000/api/client/items/item_123 \
-H "Content-Type: application/json" \
-H "Cookie: next-auth.session-token=<session_token>" \
-d '{ "name": "Updated Tool Name" }'

Delete Item (Soft Delete)

Soft-deletes an item owned by the authenticated user. The item is hidden but can be restored later.

PropertyValue
MethodDELETE
Path/api/client/items/{id}
AuthSession (user, owner)
Sourceclient/items/[id]/route.ts

Response

Status 200

{
"success": true,
"message": "Item deleted successfully"
}
StatusDescription
400Item is already deleted
401Unauthorized
403Not the item owner
404Item not found

Restore Item

Restores a previously soft-deleted item.

PropertyValue
MethodPOST
Path/api/client/items/{id}/restore
AuthSession (user, owner)
Sourceclient/items/[id]/restore/route.ts

Response

Status 200

{
"success": true,
"item": { /* restored item object */ },
"message": "Item restored successfully"
}
StatusDescription
400Item is not deleted (cannot restore an active item)
401Unauthorized
403Not the item owner
404Item not found

curl Example

curl -s -X POST http://localhost:3000/api/client/items/item_123/restore \
-H "Cookie: next-auth.session-token=<session_token>"

Get Submission Statistics

Returns statistics about the authenticated user's submissions grouped by status.

PropertyValue
MethodGET
Path/api/client/items/stats
AuthSession (user)
Sourceclient/items/stats/route.ts

Response

Status 200

{
"success": true,
"stats": {
"total": 12,
"draft": 2,
"pending": 3,
"approved": 5,
"rejected": 2,
"deleted": 1
}
}

curl Example

curl -s http://localhost:3000/api/client/items/stats \
-H "Cookie: next-auth.session-token=<session_token>"

TypeScript Usage

import type { ClientCreateItemResponse } from '@/lib/types/client-item';

// Fetch dashboard stats
const dashboardRes = await fetch('/api/client/dashboard/stats');
const dashboard = await dashboardRes.json();

// Create a new item submission
const createRes = await fetch('/api/client/items', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: 'My New Tool',
description: 'A detailed description of what this tool does.',
source_url: 'https://mytool.com',
category: 'Productivity',
}),
});
const created: ClientCreateItemResponse = await createRes.json();

// Update an item
const updateRes = await fetch(`/api/client/items/${itemId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Updated Name' }),
});
const updated = await updateRes.json();
if (updated.statusChanged) {
console.log('Item moved back to pending for re-review');
}

Error Response Pattern

All client API endpoints follow a consistent error shape:

{
"success": false,
"error": "Human-readable error message"
}

Error responses use the serverErrorResponse() utility, which logs detailed error information server-side while returning only a generic message to the client to prevent information disclosure.