Create an API
Learn how to build RESTful APIs by handling GET, POST, PUT, and DELETE requests.
Overview
In JopiJS, creating an API is as simple as creating a page. Instead of returning React components, API routes handle HTTP methods and return data (usually JSON).
In this guide, you will learn how to:
- Define API routes using file-based naming.
- Handle different HTTP methods (POST, GET, etc.).
- Retrieve request data and uploaded files.
- Return JSON or HTML responses.
1. Routing & File Naming
API routes follow the same folder structure as pages inside the @routes directory. The HTTP method you want to handle is determined by the filename:
| File Name | HTTP Method | Use Case |
|---|---|---|
onGET.ts | GET | Fetching data (conflicts with page.tsx). |
onPOST.ts | POST | Creating data or handling forms. |
onPUT.ts | PUT | Updating existing data. |
onDELETE.ts | DELETE | Removing data. |
Project Structure example:
src/
└── mod_myModuleName/
└── @routes/
└── users/
├── onGET.ts # -> GET /users
└── onPOST.ts # -> POST /users2. Handling a POST Request
Let's create an endpoint to receive JSON data. JopiJS automatically parses the request body for you.
import { JopiRequest } from "jopijs";
export default async function(req: JopiRequest) {
// 1. Get the parsed body data (JSON, Form-data, etc.)
const data = await req.req_getBodyData();
console.log("Received data:", data);
// 2. Return a JSON response
return req.res_jsonResponse({
status: "success",
message: "Message received!",
echo: data
});
}Testing with curl
curl -X POST http://localhost:3000/contact \
-H "Content-Type: application/json" \
-d '{"name": "John Doe", "email": "john@example.com"}'3. Receiving Files
JopiJS makes handling file uploads seamless. req_getBodyData() automatically detects multipart/form-data.
export default async function(req: JopiRequest) {
const data = await req.req_getBodyData();
// If "avatar" was a file field in the form
const file = data.avatar;
if (file instanceof File) {
const bytes = await file.arrayBuffer();
console.log(`Received file: ${file.name}, size: ${bytes.byteLength} bytes`);
}
return req.res_jsonResponse({ uploaded: true });
}4. Path Parameters & URL Info
Just like pages, API routes can use dynamic segments (e.g., [userId]).
import { JopiRequest } from "jopijs";
export default function(req: JopiRequest) {
// Access dynamic segments
const userId = req.req_urlParts.userId;
// Access query parameters (/users/1?active=true)
const isActive = req.req_urlInfos.searchParams.get("active");
return req.res_jsonResponse({
userId,
path: req.req_urlInfos.pathname,
isActive
});
}5. Important: onGET.ts vs page.tsx
Since both files listen for GET requests at the same URL, they cannot coexist peacefully in the same folder.
page.tsx: Intended for browser navigation (returns HTML).onGET.ts: Intended for API calls (returns Data).
Conflict resolution: If both files exist in the same folder, onGET.ts will take priority, and the page will not be displayed in the browser.
Summary of Response Methods
| Method | Description |
|---|---|
req.res_jsonResponse(data) | Returns a JSON response with the correct headers. |
req.res_htmlResponse(html) | Returns a raw HTML string. |
req.res_textResponse(text) | Returns a plain text response. |
req.res_redirect(url) | Sends a temporary redirect. |