dApp API Overview
This section describes how the RitoSwap dApp APIs are put together and how the individual endpoint pages (Token Status, Nonce, Gate Access, Form Submission Gate, Logger) relate to the underlying code.
The goal of this page is to give contributors a mental model:
- Where the API handlers live
- How request/response contracts are defined
- How the OpenAPI spec is generated from Zod
- How everything is deployed as Next.js + Vercel serverless functions
- How the APIs are covered by Vitest (unit/integration) and Supertest (E2E)
Each route then has its own dedicated MDX page for deeper, endpoint‑specific details.
Runtime & hosting
The dApp API surface is implemented using the Next.js App Router and deployed as Vercel serverless functions.
| Concern | Implementation |
|---|---|
| Framework | Next.js App Router (next@^14.2.33, 15-style app/ directory) |
| Runtime | Node.js (serverless functions on Vercel) |
| Primary dApp workspace | dapp/ (Next.js app + API routes) |
| API route handlers | dapp/app/api/**/route.ts |
| OpenAPI route | dapp/app/api/openapi/route.ts |
| Swagger UI page | dapp/app/api-docs/page.tsx |
Each HTTP endpoint documented in this section corresponds directly to a Next.js route.ts file under dapp/app/api. The docs on this site are meant to describe behavior and usage, while the OpenAPI spec is the single source of truth for the exact contracts.
The dApp API pages focus exclusively on the blockchain-relevant Next.js HTTP endpoints.
If you’re looking for the Cloudflare Worker APIs (durable state + email relay) or the AI backend APIs (LangChain chat pipeline and MCP server), those are documented in separate sections — see the cards below.
Durable state and email relay endpoints for /state actions, quotas, rate limits, and the Brevo email relay.
AI chat orchestration, LangChain flows, and model-facing HTTP endpoints.
Chat & LangChain BackendThe MCP server, tools, and agent integrations.
MCP Server & ToolsSchema-first API design with Zod & OpenAPI
All request/response contracts are defined with Zod v4 and converted into an OpenAPI document with @asteasolutions/zod-to-openapi.
Key packages:
| Package | Version | Role |
|---|---|---|
zod | ^4.0.17 | Core schema and validation library |
@asteasolutions/zod-to-openapi | ^8.1.0 | Converts Zod schemas into an OpenAPI 3 document |
swagger-ui-react | ^5.27.1 | Renders the interactive OpenAPI console in the browser |
Directory layout for schemas:
At a high level:
- Domain schemas (
dapp/app/schemas/domain) capture core business rules independent of transport (validation helpers, shared guards, value objects). - DTO schemas (
dapp/app/schemas/dto) describe the HTTP layer (request bodies, query params, path params, and responses per route). - OpenAPI schemas (
dapp/app/schemas/openapi) stitch the domain/DTO schemas into a full OpenAPI document.
extendZodWithOpenApi
The OpenAPI pipeline is built around extendZodWithOpenApi, which augments the Zod namespace with OpenAPI metadata helpers.
Typical pattern:
- Extend Zod: Call
extendZodWithOpenApi(z)once in the OpenAPI bootstrap file. - Annotate schemas: Tag DTO/domain schemas with OpenAPI metadata (examples, descriptions, parameter hints).
- Generate spec: Use
generateOpenApiDocument(or equivalent) to emit a fullopenapi.jsonintopublic/. - Serve spec:
/api/openapireads that JSON, adjusts theserversarray based on the current request/host, and returns it.
In other words: Zod is the single source of truth, and OpenAPI/Swagger are derived artifacts.
If you need to change a request/response shape, update the corresponding *.dto.ts or *.domain.ts file first, then regenerate the OpenAPI document. The HTTP handlers and tests should import the same Zod schemas to stay in lockstep.
Documentation surfaces
There are two layers of documentation for the dApp APIs:
-
Human-friendly MDX pages (this section)
- One page per major route: Token Status, Nonce Generation, Gate Access, Form Submission Gate, Logger.
- Focused on concepts, when-to-use guidance, gotchas, and examples.
-
Machine-readable OpenAPI + Swagger UI
- Generated spec at
/api/openapi(served bydapp/app/api/openapi/route.ts). - Full-page Swagger console at
/api-docs(dapp workspace).
- Generated spec at
- Embedded Swagger blocks in the docs site via
<SwaggerDocs />or<SwaggerDocs tag="..." />.
The embedded component lives at:
// docs/app/components/utilities/swaggerdocs/SwaggerDocs.tsx
<SwaggerUI
url={`${apiBaseUrl}/api/openapi`}
tryItOutEnabled
docExpansion="none"
defaultModelsExpandDepth={-1}
filter={tag || undefined}
/>On this docs site, endpoint pages use the tag filter (for example, "Token Status" or "Gate Access") to show only the relevant slice of the spec.
Testing strategy
The dApp APIs are covered at multiple levels, from pure schema tests to live HTTP calls.
Unit & integration — Vitest
Key packages:
| Package | Version | Role |
|---|---|---|
vitest | ^3.2.4 | Unit and integration test runner |
@vitest/coverage-v8 | ^3.2.4 | Coverage reporting |
@testing-library/react | ^16.3.0 | React component testing (where UI interacts with API) |
Vitest is used to:
- Assert that domain/DTO schemas accept valid payloads and reject invalid ones.
- Exercise helper libraries (logging, signing, rate-limiting, etc.).
- Validate that OpenAPI generation doesn’t drift from the Zod schemas.
End-to-end API tests — Supertest
For live HTTP behavior, the project uses Supertest:
| Package | Version | Role |
|---|---|---|
supertest | ^7.1.4 | Black-box HTTP tests hitting the Next.js handlers |
These tests:
- Spin up the API routes and hit them over HTTP (or equivalent handler adapters).
- Validate end-to-end behavior including status codes, headers, and RFC 7807 error shapes.
- Are especially important for routes like
/api/gate-accessand/api/form-submission-gate, which combine auth, chain reads, database access, and side effects.
See the Testing & QA → Supertest docs for concrete test locations and scenarios.
Endpoint index
Use the table below as the high-level map for the API docs in this section.
| Doc page | Endpoint | Purpose |
|---|---|---|
| Token Status | GET /api/token-status/[tokenId] | Lightweight polling API for checking token existence and usage. |
| Nonce Generation | GET /api/nonce | Issues SIWE nonces for login flows, with rate limiting and expiry. |
| Gate Access | POST /api/gate-access | Delivers gated content to token holders using JWT, SIWE, or legacy signatures. |
| Form Submission Gate | POST /api/form-submission-gate | One-time message submission for key holders, with email delivery and optional backdoor resets. |
| Logger | N/A (library) | API-focused logger used across serverless handlers (Winston wrapper). |
How to extend the API surface
When adding a new endpoint:
1. Define domain & DTO schemas
Add or extend a domain schema in dapp/app/schemas/domain.
Define the request/response DTOs in dapp/app/schemas/dto using Zod, with OpenAPI metadata attached.
2. Wire into OpenAPI
Register the new schemas and route under dapp/app/schemas/openapi.
Ensure the endpoint is tagged so it can be filtered by <SwaggerDocs tag="..." />.
3. Implement the handler
Create dapp/app/api/[route-name]/route.ts.
Use the shared logger, rate-limiting, and security helpers where appropriate.
4. Add tests
Add schema/logic tests under Vitest. Add or extend Supertest suites to cover happy paths and failure modes.
5. Document the endpoint
Create a new MDX page under docs/content/dapp/api.
Link to the OpenAPI spec using <SwaggerDocs tag="Your Tag" />.
Add the page to _meta.js so it appears in navigation.
This keeps schemas, handlers, docs, and tests aligned while letting the OpenAPI spec remain the canonical contract for clients.
```js
// docs/content/dapp/api/_meta.js
const meta = {
index: 'Overview',
'token-status': 'Token Status',
nonce: 'Nonce Generation',
'gate-access': 'Gate Access',
'form-submission-gate': 'Form Submission Gate',
logger: 'Logger',
};
export default meta;