> ## Documentation Index
> Fetch the complete documentation index at: https://archie.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom APIs

> Register HTTP routes that reverse-proxy to internal services with CORS, rate limiting, request transformation, circuit breakers, and caching.

Custom APIs are HTTP routes you register on Archie's gateway that reverse-proxy to internal services. Each route maps a public-facing URL path to a target URL and brings the target under the same auth, CORS, rate-limiting, and resilience policies as the rest of your backend.

Use a Custom API when:

* You have an existing internal service you want to expose under your project's domain.
* You want CORS, rate limiting, or a circuit breaker in front of a third-party endpoint.
* You need request/response transformation that doesn't belong in your service code.

For CRUD against the [Data Model](/docs/features/backend/data-model/overview), you don't need a Custom API — the auto-generated [GraphQL](/docs/features/backend/graphql-api-explorer/overview) and [REST](/docs/features/backend/rest-api-explorer/overview) APIs already cover that.

To open it, navigate to **App Services → Custom APIs** in the Backend Console.

<img src="https://mintcdn.com/archie-e998dbf6/Qol4EJyOu33nszYZ/features/backend/app-services/custom-api-gateway-overview.png?fit=max&auto=format&n=Qol4EJyOu33nszYZ&q=85&s=a70dfae05f2a035ea2e1fd608cf5d82e" alt="Custom API Gateway overview" width="1866" height="853" data-path="features/backend/app-services/custom-api-gateway-overview.png" />

## Per-environment scoping

Routes are scoped per environment. Each [environment](/docs/features/backend/environments/overview) has its own routes — production routes can point at production services while `dev` routes point at staging instances of the same service.

When branching an environment with the **Gateway routes** copy option, every route is duplicated into the new environment. Each copy receives a new ID and can be edited independently.

## Registering a route

The configuration is split across four tabs: **General**, **Security**, **Request & Response**, and **Resilience**.

### General — routing logic

The **General** tab defines what the route catches and where it goes.

| Field | Purpose |
| - | - |
| **Path** | Public-facing URI path clients call (e.g., `/api/v1/users`). |
| **Target URL** | Internal destination URL where the gateway forwards the request. |
| **Methods** | HTTP verbs the route responds to: `GET`, `POST`, `PUT`, `PATCH`, `DELETE`. |
| **Enabled** | Toggle to activate or deactivate the route without deleting it. |

<img src="https://mintcdn.com/archie-e998dbf6/Qol4EJyOu33nszYZ/features/backend/app-services/custom-api-gateway-general-config.png?fit=max&auto=format&n=Qol4EJyOu33nszYZ&q=85&s=0a911ffe73a24dc6dd7217003a07ee52" alt="General Configuration Form" width="1866" height="1022" data-path="features/backend/app-services/custom-api-gateway-general-config.png" />

### Security — CORS and rate limiting

The **Security** tab controls cross-origin access and rate limits per route.

#### CORS

| Setting | What it does |
| - | - |
| **Allow All Origins** | Accept requests from any domain. Disable to use the allowlist. |
| **Allowed Origins** | Whitelist of specific domains permitted to call the route. |
| **Allowed Methods & Headers** | HTTP verbs and custom headers the gateway will accept. |
| **Allow Credentials** | Whether browsers should include cookies or auth headers. |
| **Preflight Cache Duration** | How long browsers cache the CORS preflight response. |
| **Expose Headers** | Response headers safe to expose to the client. |

#### Rate limiting

| Setting | What it does |
| - | - |
| **Average** | Baseline requests allowed per time unit. |
| **Burst Allowance** | Extra requests allowed in short spikes above the average. |
| **Time Window** | Counting period — typically per second or per minute. |
| **Rate Limit by** | How to identify unique callers — typically by IP address. |

When the limit is exceeded, the gateway returns `429 Too Many Requests` with a `Retry-After` header.

<img src="https://mintcdn.com/archie-e998dbf6/Qol4EJyOu33nszYZ/features/backend/app-services/custom-api-gateway-route-security.png?fit=max&auto=format&n=Qol4EJyOu33nszYZ&q=85&s=e586179a9e9951c44bef317994783479" alt="Route Security Configuration" width="1866" height="1022" data-path="features/backend/app-services/custom-api-gateway-route-security.png" />

For project-wide CORS and rate-limit defaults, see [Backend → Settings → Network](/docs/features/backend/settings/network).

### Request & Response — transformations

The **Request & Response** tab controls how data is shaped on the way through the gateway.

#### Custom headers

Add or override headers per route:

* **Custom request headers** — sent to your backend on top of what the client sent.
* **Custom response headers** — added to the response on the way back.

Each header is a name and a value. Useful for injecting service-to-service auth tokens or stamping responses with a `Cache-Control` policy.

#### Path rewriting

Modify the request path before it reaches your backend:

| Operation | Example |
| - | - |
| **Strip prefix** | `/v1/users/123` → `/users/123` (strip `/v1`). |
| **Add prefix** | `/users/123` → `/api/users/123` (add `/api`). |
| **Regex pattern & replacement** | `^/old/(.*)` → `/new/$1` for arbitrary remapping. |

#### Query parameter forwarding

Choose which query string parameters reach the backend:

| Mode | Behavior |
| - | - |
| **Forward all** | Pass the entire query string unchanged. |
| **Allow list** | Forward only the named parameters. |
| **Deny list** | Forward all parameters except those explicitly blocked. |

#### Body size limits

| Setting | Purpose |
| - | - |
| **Request body size limit** | Maximum size of incoming request bodies. |
| **Response body size limit** | Maximum size of outgoing response bodies. |

Exceeding either limit returns `413 Payload Too Large`.

<img src="https://mintcdn.com/archie-e998dbf6/Qol4EJyOu33nszYZ/features/backend/app-services/custom-api-gateway-request-response.png?fit=max&auto=format&n=Qol4EJyOu33nszYZ&q=85&s=95847c675e730e3501b8893a00edc114" alt="Request and Response Settings" width="1866" height="1022" data-path="features/backend/app-services/custom-api-gateway-request-response.png" />

### Resilience — timeouts, circuit breakers, caching

The **Resilience** tab keeps your route healthy when the backend doesn't cooperate.

#### Custom timeout

How long the gateway waits for a response before giving up. Set between 1 and 300 seconds. Without a timeout, a slow backend can pin gateway capacity indefinitely.

#### Circuit breaker

Automatically stop forwarding requests to a failing backend so failures don't cascade. Apply a preset or write a custom expression:

| Preset | Trips when |
| - | - |
| **50% errors** | Error ratio crosses 0.5 over the check window. |
| **30% errors** | Error ratio crosses 0.3. |
| **High latency** | p99 response time crosses the threshold. |
| **500+ errors** | Sustained 5xx responses. |

| Setting | Purpose |
| - | - |
| **Expression** | Custom trip condition (e.g., `NetworkErrorRatio() > 0.5`). |
| **Check (s)** | How often the breaker checks while open. |
| **Fallback (s)** | Wait before attempting a partial close. |
| **Recovery (s)** | Recovery phase duration before fully closing. |

#### Response caching

| Setting | Purpose |
| - | - |
| **Cache TTL (seconds)** | Time-to-live for `GET` responses. Subsequent identical requests within the TTL are served from gateway cache. |

Caching applies only to safe (`GET`) requests. Mutations are never cached.

<img src="https://mintcdn.com/archie-e998dbf6/Qol4EJyOu33nszYZ/features/backend/app-services/custom-api-gateway-resilience.png?fit=max&auto=format&n=Qol4EJyOu33nszYZ&q=85&s=7dd88f6a232a47218da9a1d77e7e0320" alt="Resilience and Reliability Settings" width="1866" height="1022" data-path="features/backend/app-services/custom-api-gateway-resilience.png" />

## Programmatic management

Routes can also be created via GraphQL — useful for codifying gateway configuration alongside your data model.

```graphql theme={null}
mutation RegisterRoute($input: RegisterRouteInput!) {
  registerRoute(input: $input) {
    id
    path
    targetUrl
    methods
    enabled
    environment
  }
}
```

When you delete an environment, all routes attached to it are cleaned up automatically. To delete environment routes manually:

```graphql theme={null}
mutation DeleteRoutesByEnvironment($input: DeleteRoutesByEnvironmentInput!) {
  deleteRoutesByEnvironment(input: $input) {
    deletedCount
  }
}
```

## Permissions

Custom API routes inherit the same auth and authorization model as the rest of your backend. Authenticated requests carry their roles to the route, where you can apply per-route policy. For full coverage, see [Role-Based Access](/docs/features/backend/app-services/role-based-access).

## FAQ

<AccordionGroup>
  <Accordion title="When should I use a Custom API instead of a custom function?">
    Use a Custom API when you have an existing service to expose — the gateway adds CORS, rate limiting, and resilience without code. Use a custom function when the logic itself runs inside Archie. The two compose: a Custom API can route to a custom function the same way it routes to any backend.
  </Accordion>

  <Accordion title="Are routes copied between environments?">
    Optionally — tick **Gateway routes** in the branching modal. Each copy gets a new ID. After branching, edits in either environment are independent.
  </Accordion>

  <Accordion title="What's the difference between per-route CORS and the Network settings?">
    [Settings → Network](/docs/features/backend/settings/network) sets the default CORS for the auto-generated GraphQL and REST APIs. Per-route CORS overrides that for a specific Custom API path.
  </Accordion>

  <Accordion title="Can I cache POST requests?">
    No — caching only applies to `GET`. Caching mutations would silently return stale state to clients that expected fresh writes.
  </Accordion>

  <Accordion title="What happens when the circuit breaker opens?">
    The gateway short-circuits incoming requests with a `503 Service Unavailable` response without forwarding to the backend. After the recovery period, it lets a small number of probe requests through to test whether the backend has recovered before fully closing the circuit.
  </Accordion>
</AccordionGroup>
