API Configuration (api.json)
The api.json file lives in configs/ and is the single source of truth for your HTTP‑API surface. It defines routing, authentication, throttling, error formats, and more. On each boot, the framework reads this file in full to handle api requests.
Note: The API is controlled by the
enabledkey Main on/off switch.falsedisables all API routes.
How the API Works
All API requests are routed by sub‑domain first, then path:
https://{domain_id}.example.com/…- DNS – Create an
AorCNAMErecord for eachdomain_id(e.g.,api.example.com,sandbox.example.com) pointing at your app host. - Middleware – Register your global API middleware under the
apialias inconfigs/middleware.php. - Enable – Flip
"enabled"totrueinapi.json; the framework mounts all routes at boot.
To summarize:
- Choose a Subdomain: set
"domain_id"(e.g.,"api"→api.example.com). - DNS Records: point that domain to your server.
- Deploy: ensure your middleware stack under alias
apiis in place, then set"enabled": true.
How to Use
The framework ships with an
api.sample.jsoninconfigs/.
cp configs/api.sample.json configs/api.jsonLocation Place
api.jsonin theconfigs/directory of your project.Subdomain Setup Decide on a
domain_id(e.g.,"api") and create a matching subdomain (api.example.com). Ensure SSL/TLS certs cover it.Single Source of Truth All API settings—methods, auth, rate limits, error codes, etc.—live in this file. Edits take effect on next deploy.
Customization Tweak each section below—core, access control, caching, throttling, etc.—to your needs. You can safely add new keys later without breaking existing clients.
API Configuration Overview
Below is a detailed look at each key inside the top‑level api object.
API‑Level Keys
| Input | Description | Example |
|---|---|---|
enabled | Main on/off switch. false disables all API routes. | false |
domain_id | Subdomain slug—becomes https://{domain_id}.example.com | "api" |
charset | Default response encoding. | "utf-8" |
methods | Allowed HTTP verbs (array). | ["GET","POST","PUT","DELETE"] |
"api": {
"enabled": false,
"domain_id": "api",
"charset": "utf-8",
"methods": ["GET","POST","PUT","DELETE"],
...
}Access Control
| Input | Description | Example |
|---|---|---|
restricted | When true, blocks unauthenticated requests by default. | true |
auth_type | Shorthand guard: "apikey" or "jwt". | "apikey" |
"restricted": true,
"auth_type": "apikey",Tip: To switch to JWT, set both
auth_typeandauthentication.typeto"jwt"(and remove API‑key logic).
Caching
| Input | Description | Example |
|---|---|---|
cache | false = no caching, or an object when needed. | false |
"cache": false,Rate Limiting
| Input | Description | Example |
|---|---|---|
rate_limit.enabled | Toggle throttling middleware. | true |
rate_limit.requests_per_minute | Steady-state cap per token/IP per minute. | 60 |
rate_limit.burst | Extra allowance for short traffic spikes. | 120 |
"rate_limit": {
"enabled": true,
"requests_per_minute": 60,
"burst": 120
},Error Handling
| Input | Description | Example |
|---|---|---|
errors.expose_stack | Show stack traces in JSON (never in production). | false |
errors.default_locale | Fallback locale for error messages. | "en-US" |
errors.codes | Map internal codes → HTTP status. | { "NOT_FOUND":404 } |
"errors": {
"expose_stack": false,
"default_locale": "en-US",
"codes": {
"VALIDATION_FAILED": 400,
"NOT_FOUND": 404,
"SERVER_ERROR": 500
}
},Authentication
| Input | Description | Example |
|---|---|---|
authentication.type | Driver: "apikey" or "jwt". | "jwt" |
authentication.secret_env | Env var name for JWT secret. | "API_JWT_SECRET" |
authentication.token_ttl | JWT lifetime in seconds. | 3600 |
"authentication": {
"type": "jwt",
"secret_env": "API_JWT_SECRET",
"token_ttl": 3600
},Authorization (RBAC)
| Input | Description | Example |
|---|---|---|
authorization.restricted | When true, every route goes through an RBAC check. | true |
authorization.roles | Array of valid role slugs. | ["admin","user"] |
authorization.anonymous_read | Allow unauthenticated GETs if set to true. | false |
"authorization": {
"restricted": true,
"roles": ["admin","user"],
"anonymous_read": false
}Example api.json
{
"api": {
"enabled": false,
"domain_id": "api",
"charset": "utf-8",
"methods": ["GET","POST","PUT","DELETE"],
"restricted": true,
"auth_type": "apikey",
"cache": false,
"rate_limit": {
"enabled": true,
"requests_per_minute": 60,
"burst": 120
},
"errors": {
"expose_stack": false,
"default_locale": "en-US",
"codes": {
"VALIDATION_FAILED": 400,
"NOT_FOUND": 404,
"SERVER_ERROR": 500
}
},
"authentication": {
"type": "jwt",
"secret_env": "API_JWT_SECRET",
"token_ttl": 3600
},
"authorization": {
"restricted": true,
"roles": ["admin","user"],
"anonymous_read": false
}
}
}Best Practices & Notes
- Start Closed – Ship with
"enabled": falseuntil your middleware pipeline underapiis wired and tested. - One Auth Strategy – Keep
auth_typein sync withauthentication.typeto avoid confusion. - Throttle Before Auth – Place rate-limit middleware before authentication to blunt brute‑force attacks.
- Health Check – Expose a
GET /pingendpoint returning200 OKfor uptime monitors. - DNS & SSL – Automate certificate issuance for each
{domain_id}subdomain (Let’s Encrypt, etc.).