Skip to main content

Surveys API Endpoints

The Surveys API provides full CRUD operations for surveys and response collection. Surveys can be either global (site-wide) or item-specific, and support draft/published/closed lifecycle states.

Source files:

  • template/app/api/surveys/route.ts
  • template/app/api/surveys/[surveyId]/route.ts
  • template/app/api/surveys/[surveyId]/responses/route.ts
  • template/app/api/surveys/responses/[responseId]/route.ts

Endpoint Summary

MethodPathAuthDescription
GET/api/surveysOptionalList surveys with filters
POST/api/surveysAdminCreate a new survey
GET/api/surveys/{surveyId}ConditionalGet a single survey by ID or slug
PUT/api/surveys/{surveyId}AdminUpdate a survey
DELETE/api/surveys/{surveyId}AdminDelete a survey
GET/api/surveys/{surveyId}/responsesAdminList responses for a survey
POST/api/surveys/{surveyId}/responsesOptionalSubmit a response
GET/api/surveys/responses/{responseId}AdminGet a single response

GET /api/surveys

Retrieves a paginated list of surveys with optional filtering. Database availability is checked before processing.

Query Parameters

ParameterTypeRequiredDefaultDescription
type"global" or "item"No--Filter by survey type
itemIdstringNo--Filter by associated item ID
status"draft", "published", or "closed"No--Filter by status
pageintegerNo1Page number (minimum 1)
limitintegerNo10Items per page (1-100)

Response Shape

200 -- Surveys Retrieved

{
"success": true,
"data": {
"surveys": [
{
"id": "survey_abc123",
"title": "User Satisfaction Survey",
"type": "global",
"status": "published",
"surveyJson": { "questions": [] }
}
],
"total": 25,
"totalPages": 3,
"page": 1
}
}

Error Handling

The endpoint has special handling for common database errors:

  • Connection errors (missing DATABASE_URL, refused connections) return 503 with a descriptive message.
  • Schema errors (missing tables/relations) return 503 suggesting migrations need to run.
  • Other errors return 500.

POST /api/surveys

Creates a new survey. Requires admin authentication.

Request Body

FieldTypeRequiredDescription
titlestringYesSurvey title
descriptionstringNoSurvey description
type"global" or "item"YesSurvey type
itemIdstringNoAssociated item ID (for item-type surveys)
status"draft", "published", or "closed"NoInitial status
surveyJsonobjectYesSurvey definition (questions, structure)

Response: 201 Created

{
"success": true,
"data": {
"id": "survey_new123",
"title": "New Survey",
"type": "global",
"status": "draft",
"surveyJson": { "questions": [] }
}
}

GET /api/surveys/{surveyId}

Retrieves a single survey by its ID or slug. Non-published surveys are only visible to admins.

Access Control Logic

// Published surveys are visible to everyone
if (survey.status !== 'published') {
const session = await auth();
if (!session?.user?.isAdmin) {
return NextResponse.json(
{ success: false, error: 'Survey not found' },
{ status: 404 }
);
}
}

The endpoint first attempts lookup by ID, then falls back to slug-based lookup.

Response: 404 Not Found

Returned when the survey does not exist OR when a non-admin requests a non-published survey:

{
"success": false,
"error": "Survey not found"
}

PUT /api/surveys/{surveyId}

Updates an existing survey. Requires admin authentication. The handler first resolves the survey by ID or slug before applying updates.

Request Body

FieldTypeRequiredDescription
titlestringNoUpdated title
descriptionstringNoUpdated description
status"draft", "published", or "closed"NoUpdated status
surveyJsonobjectNoUpdated survey definition

Response: 200 Updated

{
"success": true,
"data": { "id": "survey_abc", "title": "Updated Title" },
"message": "Survey updated successfully"
}

DELETE /api/surveys/{surveyId}

Permanently deletes a survey. Requires admin authentication.

Response: 200 Deleted

{
"success": true,
"data": null,
"message": "Survey deleted successfully"
}

GET /api/surveys/{surveyId}/responses

Retrieves paginated responses for a specific survey. Requires admin authentication.

Query Parameters

ParameterTypeRequiredDescription
itemIdstringNoFilter responses by item ID
userIdstringNoFilter responses by user ID
startDatestring (date)NoFilter responses from this date
endDatestring (date)NoFilter responses until this date
pageintegerNoPage number
limitintegerNoItems per page

Response: 200

{
"success": true,
"data": {
"responses": [
{
"id": "resp_123",
"surveyId": "survey_abc",
"userId": "user_456",
"itemId": null,
"data": { "q1": "answer1" },
"completedAt": "2024-01-20T10:30:00.000Z",
"ipAddress": "192.168.1.1",
"userAgent": "Mozilla/5.0...",
"createdAt": "2024-01-20T10:30:00.000Z"
}
],
"total": 42,
"totalPages": 5
}
}

POST /api/surveys/{surveyId}/responses

Submits a response to a published survey. Authentication is optional -- anonymous submissions are supported. The endpoint captures IP address and user agent metadata.

Request Body

FieldTypeRequiredDescription
dataobjectYesSurvey response data (answers)

How Metadata Is Captured

const forwardedFor = request.headers.get('x-forwarded-for') || '';
const ipAddress =
(forwardedFor.split(',')[0]?.trim()) ||
request.headers.get('x-real-ip') ||
'unknown';

const userAgent = request.headers.get('user-agent') || 'unknown';

Response: 201 Created

{
"success": true,
"data": {
"id": "resp_new123",
"surveyId": "survey_abc",
"data": { "q1": "my answer" },
"completedAt": "2024-01-20T10:30:00.000Z"
},
"message": "Response submitted successfully"
}

400 -- Invalid Body

{
"success": false,
"error": "Invalid request body: \"data\" is required"
}

GET /api/surveys/responses/{responseId}

Retrieves a single survey response by ID. Requires admin authentication.

Response: 200

{
"success": true,
"data": {
"id": "resp_123",
"surveyId": "survey_abc",
"userId": "user_456",
"data": { "q1": "answer1" },
"completedAt": "2024-01-20T10:30:00.000Z"
}
}

FilePurpose
template/app/api/surveys/route.tsList and create surveys
template/app/api/surveys/[surveyId]/route.tsSingle survey CRUD
template/app/api/surveys/[surveyId]/responses/route.tsSurvey response list and submit
template/app/api/surveys/responses/[responseId]/route.tsSingle response retrieval
template/lib/services/survey.service.tsSurvey business logic
template/lib/types/survey.tsTypeScript types and interfaces