From wix-cli
Creates HTTP endpoints for Wix CLI apps. Use only when the user specifically asks for a backend endpoint. Use when building REST API endpoints, backend HTTP handlers, or server-side logic. Triggers include backend API, HTTP endpoint, HTTP methods, form handling, file uploads.
npx claudepluginhub wix-playground/skills-architecture-test --plugin wix-cliThis skill uses the workspace's default tool permissions.
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.
Builds REST API routes, webhooks, and form handlers in Astro projects using .ts endpoint files in src/pages/ and middleware for auth, cookies, logging. For SSR/hybrid mode with co-located backend.
Builds production-ready REST API endpoints with input validation, authentication checks, error handling, business logic, and documentation for Express and Fastify. Useful for creating CRUD operations and backend routes.
Scaffolds Hono API routes for Cloudflare Workers with Zod validation, middleware, typed bindings, error handling, and endpoint documentation. Use post-project setup to add endpoints.
Share bugs, ideas, or general feedback.
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:
src/pages/api/ with .ts extensionnpm run generate — create files directlyUse HTTP endpoints when you need to:
File path determines the endpoint URL:
src/pages/api/<your-endpoint-name>.ts
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
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.
};
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
};
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
};
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" },
});
}
};
const authHeader = request.headers.get("Authorization");
const contentType = request.headers.get("Content-Type");
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" },
});
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();
To take HTTP endpoints to production, build and release your project:
build command.preview command to share with team members for testing.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.
src/pages/api/
├── users.ts # /api/users endpoint
├── users/
│ └── [id].ts # /api/users/:id endpoint
└── posts.ts # /api/posts endpoint
any, explicit return types)APIRoute from astroResponse objects with JSON.stringify() for JSONContent-Type: application/json header on JSON responsesstatusText in error responses@ts-ignore comments