Build API endpoints with +server.ts files — return JSON, handle GET and POST, read params and the query string.
Why: a +server.ts file is an API endpoint. Export a function named after the HTTP method (GET, POST, …) and return a Response. The json() helper builds a JSON response for you. Note: a folder can hold a +page.svelte OR a +server.ts, not both.
// src/routes/api/posts/+server.ts -> GET /api/posts
import { json } from '@sveltejs/kit'
import type { RequestHandler } from './$types'
export const GET: RequestHandler = async () => {
return json({ message: 'Hello!' })
}Why: to accept data, export POST and read the request body. request.json() parses a JSON payload; return a 201 status to signal "created".
// src/routes/api/posts/+server.ts
import { json } from '@sveltejs/kit'
import type { RequestHandler } from './$types'
export const POST: RequestHandler = async ({ request }) => {
const body = await request.json()
// ...save body
return json({ created: body }, { status: 201 })
}Why: just like pages, [id] in the path becomes a param, available on the params object. Use it to look up one record.
// src/routes/api/posts/[id]/+server.ts -> GET /api/posts/123
import { json } from '@sveltejs/kit'
import type { RequestHandler } from './$types'
export const GET: RequestHandler = async ({ params }) => {
return json({ id: params.id })
}Why: values after the ? in the URL come from url.searchParams. Use them for search, filtering, or pagination.
// src/routes/api/search/+server.ts -> /api/search?q=svelte
import { json } from '@sveltejs/kit'
import type { RequestHandler } from './$types'
export const GET: RequestHandler = async ({ url }) => {
const q = url.searchParams.get('q') ?? ''
return json({ query: q })
}