Build an HTTP Endpoint in Studio Two

An HTTP endpoint is a TypeScript file in src/api/ that handles HTTP requests on Wix servers. You generate the file first, then write handlers that check the caller, do the work, and return a response. Your frontend code calls those handlers.

This article walks through that loop, from a scaffolded endpoint to one that lets logged-in site members post a product review. The handler validates the review and saves it to a CMS collection that site members can't write to directly.

To follow the example, first create a collection with the ID Reviews and these fields:

  • productId: Text.
  • rating: Number.
  • text: Text.
  • memberId: Text.

Set read to ANYONE, so site visitors can see reviews, and keep insert, update, and remove set to ADMIN, so only the endpoint's elevated call can add one.

Follow the instructions below to:

  1. Scaffold the endpoint.
  2. Set the route.
  3. Write the handlers.
  4. Check the caller.
  5. Call Wix APIs.
  6. Call the endpoint from your frontend code.
  7. Check the endpoint.
  8. Publish your site with the endpoint.

Step 1 | Scaffold the endpoint

Start from a generated HTTP endpoint rather than an empty file, so the imports and handler types are already in place.

To generate the endpoint, follow Step 1 of Add an HTTP Endpoint Extension in Studio Two, and enter reviews in Name.

You can find the new file at src/api/reviews.ts. Wix serves it at the route reviews. You spend most of this article in that file.

Step 2 | Set the route

The endpoint file's path in src/api/ sets its route. Wix drops the file extension, so src/api/reviews.ts serves the route reviews. Every .ts or .js file in src/api/, except .d.ts files, becomes a route, so keep shared helper code, such as validation functions, outside src/api/.

To rename or move a route, rename or move the file. For index files, dynamic segments such as [reviewId].ts, and the routes Wix reserves, see Routes in a Studio Two site.

Step 3 | Write the handlers

Each handler is an exported constant named for the HTTP method it handles, such as GET, POST, PUT, or DELETE, and typed as APIRoute from @wix/custom-extensions/types. A handler receives a context object and returns a standard Response.

The context object holds the incoming request, the request url, and the route's dynamic params. For what each property contains, see Handler context.

Errors and logging

Return Response.json() to send JSON. To report an expected failure, such as invalid input, set the status yourself. If a handler throws an error that it doesn't catch, the caller gets a 500 response with the body Internal Server Error, and the error message stays on the server.

Wix logs uncaught errors from a handler automatically, so you can find their details on the Logs page in the site dashboard. To record what a handler does, or an error that it catches, write log entries.

Validate the request

To accept a review and reject invalid input with a 400 response, replace the contents of src/api/reviews.ts with the following code. The code keeps the generated APIRoute import and replaces the generated GET and POST handlers with a single POST handler.

Copy

The try block around request.json() turns a body that isn't valid JSON into a 400 response instead of an uncaught error. The handler doesn't save anything yet. You add the save in Step 5.

Step 4 | Check the caller

An HTTP endpoint has no built-in permissions, so any site visitor can call it. Check who the caller is before you do anything on their behalf.

To read the caller's identity, call auth.getTokenInfo() from @wix/essentials. It returns details from the caller's access token, including:

  • subjectType: The kind of caller:
    • VISITOR: A site visitor who isn't logged in.
    • MEMBER: A logged-in site member.
    • USER: A Wix user, such as the site owner or a collaborator.
  • subjectId: The caller's ID, such as the member ID.

For example, to accept reviews only from logged-in site members, import auth at the top of src/api/reviews.ts:

Copy

Then, add a check at the start of the POST handler, before the code that reads the request body:

Copy

Check for the identity you allow, rather than ruling out the ones you don't. That way, a caller you didn't plan for is rejected.

When you need the caller's ID, take it from tokenInfo.subjectId. Don't trust an ID that the request body or URL sends, because the caller controls those values.

Step 5 | Call Wix APIs

Wix API calls in a handler run with the caller's identity. A call succeeds only if the caller is allowed to make it. For example, a site visitor can't query the site's contacts, so the call fails with a permissions error.

To run one call with elevated permissions, wrap the method with auth.elevate() from @wix/essentials, then call the wrapped method. Only calls through the wrapped method are elevated. The rest of the handler still runs as the caller.

For example, to save the review to the Reviews collection, which site members can't add items to, import items at the top of src/api/reviews.ts:

Copy

Then, in the POST handler, replace return Response.json({ valid: true }); with the following code. It uses productId, rating, and text from Step 3 and tokenInfo from Step 4:

Copy

Caution: An elevated call ignores the permissions of the caller and of the collection. Before an elevated call, check the caller, as in Step 4, and validate everything that the request sends, as in Step 3.

To call a 3rd-party API, store its key in the Secrets Manager. In the handler, read the key with Get Secret Value from @wix/secrets, wrapped with auth.elevate(). Code in an HTTP endpoint runs on Wix servers, so the key never reaches the browser.

The complete endpoint

Here's the complete src/api/reviews.ts, with the handlers from Steps 3 through 5:

Copy

Step 6 | Call the endpoint from your frontend code

Call the endpoint from frontend code, such as an Editor React Component (ERC), a Data Source, or a dashboard page, with httpClient.fetchWithAuth() from @wix/essentials. The method attaches the caller's access token, which every endpoint request needs. A request without a token fails with a 401 response before your handler runs.

Build the request

Build the endpoint URL from two parts:

  • The origin of import.meta.url, which is the domain that serves your code. Wix serves endpoints from a different domain than your site's pages.
  • The server base path in import.meta.env.WIX_SERVER_BASE_PATH, which ends with /. If the value isn't set, use /.

Add the route after the base path, without a leading /. A URL that starts with /, such as '/reviews', resolves against the page's own domain, and on a site page it returns a 404 response.

For example, to send a review to the endpoint, add this function to a frontend code file outside src/api/, such as src/lib/post-review.ts, and import it where you need it:

Copy

Handle the response

fetchWithAuth() behaves like fetch(), so it doesn't throw an error for a 4xx or 5xx response. Check response.ok or response.status, and show site visitors a message they can act on, such as asking them to log in after a 403 response.

The request body is plain JSON, so send only values that JSON supports. For example, a Date arrives as a string, and properties set to undefined are dropped.

Call it from an ERC or Data Source

In an ERC, call a function like postReview() from an event handler, such as a button's click handler. In a Data Source, expose it as a function in the provider's context.items, so that components on the page can connect to it.

Step 7 | Check the endpoint

To check the endpoint:

  1. Call postReview() from a dashboard page, as in Step 3 of Add an HTTP Endpoint Extension in Studio Two. A dashboard page calls the endpoint as you, a Wix user, not as a site member, so the endpoint returns a 403 response, and postReview() throws an error that includes Status: 403. That error shows that the caller check works.
  2. Publish your site, then post a review as a logged-in site member on the live site. Check that the new item appears in the Reviews collection.

Note: In the Studio Two editor and Preview, calls from site code fail with a 403 response while your code changes aren't deployed yet. After you publish your site, the calls work there and on the live site. Calls from a dashboard page work as soon as you save your code.

Step 8 | Publish your site

When the endpoint behaves the way you want, click Publish in the Studio Two editor to ship it with your site.

See also

Last updated: 2 November 2026

Did this help?