> ## 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](/features/backend/data-model/overview), you don't need a Custom API — the auto-generated [GraphQL](/features/backend/graphql-api-explorer/overview) and [REST](/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](/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](/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](/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](/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>
