---
title: "API conventions"
url: https://memory.wiki/LhYW7tc1
updated: 2026-05-27T00:41:53.897Z
hub: https://memory.wiki/hub/demo
bundle_count: 1
concept_count: 12
source: "demo-seed"
---
# API conventions

## URL shape

`/api/v1/<resource>` for stable endpoints. Versioned via the path. Sub-resources nest: `/api/v1/pages/<id>/blocks`.

## HTTP verbs

- `GET` — idempotent read
- `POST` — create
- `PATCH` — partial update (default for edits)
- `PUT` — full replace (rare, use sparingly)
- `DELETE` — soft delete (sets `deleted_at`); pass `?permanent=true` for hard delete

## Error shape

Every error response:

```json
{
  "error": "human-readable message",
  "code": "machine_code",
  "details": {}
}
```

Status codes used: 400 (bad input), 401 (no auth), 403 (auth but no permission), 404 (not found), 409 (conflict), 410 (gone — expired), 422 (validation), 429 (rate limit), 500 (us).

## Authentication

Two paths, in order of precedence:

1. `Authorization: Bearer <jwt>` — for signed-in users (preferred)
2. `x-edit-token: <token>` — for anonymous edits (per-doc capability)

Server middleware (`lib/verify-auth.ts`) returns `{userId, email}`or null. Routes that allow either signed-in or token holders should check both.

## Rate limiting

Sliding window, IP-based, 60 req/min default. Override per-route in `middleware.ts`. Returns 429 with `Retry-After` header.

## Pagination

Cursor-based, not offset. `?cursor=<opaque>&limit=20`. Response includes `nextCursor` (or null if last page).

## Things to avoid

- Don't put service-role key calls behind the public API. Use server-component reads or the cron path.
- Don't return more than 200 rows in one response. Paginate.
- Don't emit raw Postgres errors to clients — sanitize via `mapPgError`.

---

## Summary
The API uses versioned paths, HTTP verbs mapped to standard operations with soft deletes by default, and consistent error shapes with machine codes. Authentication supports JWT tokens for signed-in users and per-document capability tokens for anonymous edits, with rate limiting at 60 requests per minute and cursor-based pagination capped at 200 rows per response.

## Themes
- RESTful API design patterns
- Security and authentication
- Error handling and client feedback
- Rate limiting and pagination
- Best practices and constraints

## Key takeaways
- Stable endpoints use the URL pattern /api/v1/<resource> with versioning via the path and nested sub-resources.
- HTTP verbs follow standard REST conventions: GET for reads, POST for creation, PATCH for partial updates, PUT for full replacement, and DELETE for soft deletes.
- Authentication uses either JWT bearer tokens for signed-in users or per-document edit tokens for anonymous access, checked in that order.
- Rate limiting defaults to 60 requests per minute per IP address using a sliding window algorithm and can be overridden per route.
- All error responses include a human-readable message, a machine code, and a details object, with specific status codes for different error types.
- Service-role API keys must not be exposed through the public API and should only be used server-side or in cron jobs.

## Insights
- The API uses path-based versioning rather than header-based versioning, making version information visible in every request URL.
- Authentication supports two independent mechanisms with explicit precedence ordering, allowing both authenticated users and anonymous document editors.
- The error response structure is standardized across all endpoints, including machine-readable codes alongside human-readable messages for consistent client handling.
- Soft deletes are the default behavior with hard deletes requiring explicit opt-in, suggesting a design philosophy favoring data recovery over immediate destruction.

## Open questions / gaps
- What format or structure should opaque cursor values follow for pagination implementation?
- How are the details object contents structured for different error codes, particularly for validation (422) errors?
- What specific error codes are available through the machine_code field beyond the documented status codes?

## Concepts in this document
- **Supabase** _(entity)_
  Backend-as-a-service providing authentication, database, and row-level security without separate auth overhead.
- **Vendor consolidation** _(concept)_
  The operational principle of reducing authentication surfaces, SDKs, and control planes by keeping vector search within the existing Postgres infrastructure.
- **pgvector** _(entity)_
  PostgreSQL extension providing vector data type and HNSW indexing for efficient similarity search.
- **Authentication** _(tag)_
  Core security domain covering user identity, session management, and authorization patterns.
- **Database Design** _(tag)_
  Data modeling domain including schema design, migrations, and query optimization strategies.
- **API Design** _(tag)_
  RESTful interface design covering endpoints, error handling, and client-server communication.
- **Resend** _(entity)_
  Email service provider supporting both transactional and marketing communication channels.
- **Vercel AI Gateway** _(entity)_
  AI provider abstraction layer offering failover and zero data retention for model access.
- **Next.js App Router** _(entity)_
  Chosen routing framework leveraging RSC and Server Actions to match the project's data-heavy, read-mostly workload.
- **Next.js 15** _(entity)_
  Chosen frontend framework leveraging React Server Components and caching for performance.
- **Row-level security** _(concept)_
  Supabase RLS capability co-locating authentication and authorization with data, justifying single-vendor consolidation.
- **React Hook Form** _(entity)_
  Primary form handling library paired with Zod schemas for both client and server validation.

## Concept relations (within this doc's concepts)
- **Supabase** enables approach **Vendor consolidation**
- **Supabase** implements **Row-level security**
- **Supabase** hosts **pgvector**
- **Vercel AI Gateway** similar pattern **Resend**
- **Supabase** exemplifies approach **Vendor consolidation**
- **Row-level security** supports decision **Vendor consolidation**
- **Supabase** reduces complexity **Vendor consolidation**
- **Row-level security** supports **Vendor consolidation**
- **Supabase** integrates **pgvector**
- **Supabase** exemplifies strategy **Vendor consolidation**
- **Supabase** provides **Row-level security**
- **Vendor consolidation** guides **Supabase**
- **Vendor consolidation** guides **Vercel AI Gateway**

## Bundles containing this document
- [Cross-tool dev workflow](https://memory.wiki/b/p_mdtSk0)
  > Acme Pulse, a fictional landing-page builder. The seven docs in this bundle are the project's living context — README, auth pattern, DB schema, API conventions, UI patterns, decision log, open questio

_Hub canonical:_ https://memory.wiki/hub/demo
_Concept digest:_ https://memory.wiki/raw/hub/demo?digest=1&compact=1
