Wix Backend API Builder
Creates HTTP endpoints for Wix CLI applications — server-side routes that handle HTTP requests, process data, and return responses. HTTP endpoints are powered by Astro endpoints and are automatically discovered from the file system.
Key facts:
Files live in
src/pages/api/
with
.ts
extension
Cannot be added via
npm run generate
— create files directly
Don't appear on the Extensions page in the app dashboard
No extension registration needed (auto-discovered)
Replace the legacy "HTTP functions" from the previous Wix CLI for Apps
Use Cases
Use HTTP endpoints when you need to:
Build REST APIs with multiple HTTP methods
Integrate with external APIs or services
Handle complex form submissions or file uploads
Serve dynamic content (images, RSS feeds, personalized data)
Access runtime data or server-side databases
File Structure and Naming
Basic Endpoint
File path determines the endpoint URL:
src/pages/api/.ts
Dynamic Routes
Use square brackets for dynamic parameters:
src/pages/api/users/[id].ts → /api/users/:id
src/pages/api/posts/[slug].ts → /api/posts/:slug
src/pages/api/users/[userId]/posts/[postId].ts → /api/users/:userId/posts/:postId
HTTP Methods
Export named functions for each HTTP method. Type with
APIRoute
from
astro
. Each handler receives a
request
object and returns a
Response
:
import
type
{
APIRoute
}
from
"astro"
;
export
const
GET
:
APIRoute
=
async
(
{
request
}
)
=>
{
console
.
log
(
"Log from GET."
)
;
// This message logs to your CLI.
return
new
Response
(
"Response from GET."
)
;
// This response is visible in the browser console
}
;
export
const
POST
:
APIRoute
=
async
(
{
request
}
)
=>
{
const
data
=
await
request
.
json
(
)
;
console
.
log
(
"Log POST with body: "
,
data
)
;
// This message logs to your CLI.
return
new
Response
(
JSON
.
stringify
(
data
)
)
;
// This response is visible in the browser console.
}
;
Request Handling
Path Parameters
export
const
GET
:
APIRoute
=
async
(
{
params
}
)
=>
{
const
{
id
}
=
params
;
// From /api/users/[id]
if
(
!
id
)
{
return
new
Response
(
JSON
.
stringify
(
{
error
:
"ID required"
}
)
,
{
status
:
400
,
statusText
:
"Bad Request"
,
headers
:
{
"Content-Type"
:
"application/json"
}
,
}
)
;
}
// Use id to fetch data
}
;
Query Parameters
Use
new URL(request.url).searchParams
:
export
const
GET
:
APIRoute
=
async
(
{
request
}
)
=>
{
const
url
=
new
URL
(
request
.
url
)
;
const
search
=
url
.
searchParams
.
get
(
"search"
)
;
const
limit
=
parseInt
(
url
.
searchParams
.
get
(
"limit"
)
||
"10"
,
10
)
;
const
offset
=
parseInt
(
url
.
searchParams
.
get
(
"offset"
)
||
"0"
,
10
)
;
// Use query parameters
}
;
Request Body
Parse JSON body from POST/PUT/PATCH requests:
export
const
POST
:
APIRoute
=
async
(
{
request
}
)
=>
{
try
{
const
body
=
await
request
.
json
(
)
;
const
{
title
,
content
}
=
body
;
if
(
!
title
||
!
content
)
{
return
new
Response
(
JSON
.
stringify
(
{
error
:
"Title and content required"
}
)
,
{
status
:
400
,
statusText
:
"Bad Request"
,
headers
:
{
"Content-Type"
:
"application/json"
}
,
}
)
;
}
// Process data
}
catch
{
return
new
Response
(
JSON
.
stringify
(
{
error
:
"Invalid JSON"
}
)
,
{
status
:
400
,
statusText
:
"Bad Request"
,
headers
:
{
"Content-Type"
:
"application/json"
}
,
}
)
;
}
}
;
Headers
const
authHeader
=
request
.
headers
.
get
(
"Authorization"
)
;
const
contentType
=
request
.
headers
.
get
(
"Content-Type"
)
;
Response Patterns
Always return a
Response
object with proper status codes and headers:
// 200 OK
return
new
Response
(
JSON
.
stringify
(
{
data
:
result
}
)
,
{
status
:
200
,
headers
:
{
"Content-Type"
:
"application/json"
}
,
}
)
;
// 201 Created
return
new
Response
(
JSON
.
stringify
(
{
id
:
newId
,
...
data
}
)
,
{
status
:
201
,
headers
:
{
"Content-Type"
:
"application/json"
}
,
}
)
;
// 204 No Content (for DELETE)
return
new
Response
(
null
,
{
status
:
204
}
)
;
// 400 Bad Request
return
new
Response
(
JSON
.
stringify
(
{
error
:
"Invalid input"
}
)
,
{
status
:
400
,
statusText
:
"Bad Request"
,
headers
:
{
"Content-Type"
:
"application/json"
}
,
}
)
;
// 404 Not Found
return
new
Response
(
JSON
.
stringify
(
{
error
:
"Not found"
}
)
,
{
status
:
404
,
statusText
:
"Not Found"
,
headers
:
{
"Content-Type"
:
"application/json"
}
,
}
)
;
// 500 Internal Server Error
return
new
Response
(
JSON
.
stringify
(
{
error
:
"Internal server error"
}
)
,
{
status
:
500
,
statusText
:
"Internal Server Error"
,
headers
:
{
"Content-Type"
:
"application/json"
}
,
}
)
;
Frontend Integration
Call HTTP endpoints from frontend components using Wix's built-in HTTP client (
httpClient.fetchWithAuth()
):
import
{
httpClient
}
from
"@wix/essentials"
;
// GET request
const
baseApiUrl
=
new
URL
(
import
.
meta
.
url
)
.
origin
;
const
res
=
await
httpClient
.
fetchWithAuth
(
${
baseApiUrl
}
/api/<your-endpoint-name>
,
)
;
const
data
=
await
res
.
text
(
)
;
// POST request
const
res
=
await
httpClient
.
fetchWithAuth
(
${
baseApiUrl
}
/api/<your-endpoint-name>
,
{
method
:
"POST"
,
body
:
JSON
.
stringify
(
{
message
:
"Hello from frontend"
}
)
,
}
,
)
;
const
data
=
await
res
.
json
(
)
;
Build, Deploy, and Delete
To take HTTP endpoints to production, build and release your project:
Build the project assets using the
build
command.
Optionally create preview URLs using the
preview
command to share with team members for testing.
Release your project using the
release
command.
Once released, endpoints are accessible at production URLs and handle live traffic.
To delete an HTTP endpoint, remove the file under
src/pages/api/
and release again.
Output Structure
src/pages/api/
├── users.ts # /api/users endpoint
├── users/
│ └── [id].ts # /api/users/:id endpoint
└── posts.ts # /api/posts endpoint
Code Quality Requirements
Strict TypeScript (no
any
, explicit return types)
Type all handlers with
APIRoute
from
astro
Always return
Response
objects with
JSON.stringify()
for JSON
Proper HTTP status codes (200, 201, 204, 400, 404, 500)
Include
Content-Type: application/json
header on JSON responses
Include
statusText
in error responses
Handle errors with try/catch blocks
Validate input parameters and request bodies
Use async/await for asynchronous operations
No
@ts-ignore
comments
Verification
After implementation, use
wix-cli-app-validation
to validate TypeScript compilation, build, preview, and runtime behavior.