# Request Headers

> Every request header API Maker understands - the tokens, the case and format of the response, flat objects, metadata, caching, encryption of the payload and the reply, the language of the messages, the tenant, the sandbox and compression - with an example of each.

Source: https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html

Headers change how API Maker answers a call, without changing the URL. They work on every API : generated, schema, custom, system and third party. The response carries a few headers of its own, listed at the end.

## All headers

| Header | Values | What it does |
|---|---|---|
| [`x-am-authorization`](https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html#x-am-authorization) | a token | The API user : which application calls. Needed unless the API is public. |
| [`x-am-user-authorization`](https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html#x-am-user-authorization) | a token | The person, from a DB token generator. |
| [`x-aws-authorization`](https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html#x-aws-authorization), [`x-google-authorization`](https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html#x-google-authorization), [`x-azure-authorization`](https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html#x-azure-authorization), [`x-custom-authorization`](https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html#x-custom-authorization) | a token | The person, from AWS Cognito, Google, Azure AD or a custom provider. |
| [`x-am-response-case`](https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html#x-am-response-case) | `camelCase`, `snakeCase`… | The case of every key of the answer. |
| [`x-am-content-type-response`](https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html#x-am-content-type-response) | `application/json`, `text/xml`, `text/yaml`… | The format of the answer. |
| [`x-am-response-object-type`](https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html#x-am-response-object-type) | `no_action`, `make_flat` | Flatten nested objects. |
| [`x-am-meta`](https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html#x-am-meta) | `true`, `false` | Execution time, plan, groups and sandbox in `meta`. |
| [`x-am-cache-control`](https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html#x-am-cache-control) | `no_action`, `reset_cache` | Skip the cache for this call. |
| [`x-am-get-encrypted-data`](https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html#x-am-get-encrypted-data) | `no_encryption`, `get_only_encryption`, `get_data_and_encryption` | Encrypt the answer. |
| [`x-am-encrypted-payload`](https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html#x-am-encrypted-payload) | `true` | The body is encrypted. |
| [`x-am-internationalization`](https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html#x-am-internationalization) | the name of a language | The language of the messages. |
| [`x-am-tenant-username`](https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html#x-am-tenant-username) | a tenant | The tenant of a multi-tenant instance. |
| [`x-am-sandbox-timeout`](https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html#x-am-sandbox-timeout) | milliseconds | How long the code of the call may run. |
| [`x-am-run-in-sandbox`](https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html#x-am-run-in-sandbox) | `0`, `1`, `2`… | Which sandboxes may run the code. |
| [`x-no-compression`](https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html#x-no-compression), [`accept-encoding`](https://docs.apimaker.dev/v1/docs/apis-all/header/requestHeader.html#accept-encoding) | `true` / `br`, `gzip`, `deflate`, `identity` | Compression of the answer. |

## x-am-authorization

The token of an [API user](https://docs.apimaker.dev/v1/docs/apis-security/api-user-permission.html) : the application calling. Its [groups](https://docs.apimaker.dev/v1/docs/apis-security/api-group-permission.html) decide which APIs, tables and fields the call may reach. The token comes from the [token API](https://docs.apimaker.dev/v1/docs/apis-all/system-apis/system-generated-token-api.html) and expires after `jwtOptions.expiresIn` seconds (72 hours by default, `expiresInSeconds` in the token request changes it).

```text
x-am-authorization: eyJhbGciOiJIUzI1NiIsInR1BydlRrblJlcS
```

- Missing or invalid : `401`. Valid but no group grants the API : `403`.
- Public APIs (`apiAccessType: IS_PUBLIC` in the [settings](https://docs.apimaker.dev/v1/docs/settings/apiSettings.html)) do not need it.
- Read it in your code from `g.req.auth.authAMUser`.

## x-am-user-authorization

The token of a **person**, a row of your own users table, made by a DB token generator ([auth provider](https://docs.apimaker.dev/v1/docs/authorization/AMDB.html)) through the token API. It is required when the settings of the database, the table, the API or the custom API list that provider in `authProviders`.

```text
x-am-user-authorization: eyJhbGciOiJIpXVCJBydlRrblJlcS
```

- Read it in your code from `g.req.auth.authAMDB` : the columns of the user selected by the generator, and the groups of the groups column.
- A token made for a tenant works for that tenant only, see [Multi-tenant](https://docs.apimaker.dev/v1/docs/features/multi-tenant.html#users-of-a-tenant).

## x-aws-authorization

The access token of AWS Cognito, when an [AWS auth provider](https://docs.apimaker.dev/v1/docs/authorization/AWS.html) is configured. Read from `g.req.auth.authAWS`.

```text
x-aws-authorization: eyJhbGciOInR5cCI6IkpXVCJ9
```

## x-google-authorization

The id token of a Google sign-in, when a [Google auth provider](https://docs.apimaker.dev/v1/docs/authorization/Google.html) is configured. Read from `g.req.auth.authGoogle`.

```text
x-google-authorization: eyJhbGciOiJIUzI1I6IkpXVCJ9
```

## x-azure-authorization

The token of Azure Active Directory, when an [Azure auth provider](https://docs.apimaker.dev/v1/docs/authorization/Azure.html) is configured. Read from `g.req.auth.authAzure`.

```text
x-azure-authorization: eyJhbGciOiJIUzI1NI6IkpXVCJ9
```

## x-custom-authorization

The token of a [custom auth provider](https://docs.apimaker.dev/v1/examples/req/auth/authCustom.html) : your own generator and validator code. What the validator returns is in `g.req.auth.authCustom`.

```text
x-custom-authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
```

## x-am-response-case

Changes the case of every key of the answer, nested objects and arrays included. Default : `noChange`.

| Value | `first_name` becomes |
|---|---|
| `noChange` | `first_name` |
| `camelCase` | `firstName` |
| `capitalCase` | `First Name` |
| `constantCase` | `FIRST_NAME` |
| `dotCase` | `first.name` |
| `headerCase` | `First-Name` |
| `noCase` | `first name` |
| `paramCase` | `first-name` |
| `pascalCase` | `FirstName` |
| `pathCase` | `first/name` |
| `sentenceCase` | `First name` |
| `snakeCase` | `first_name` |

### NoChange response

```text
x-am-response-case: noChange
```

### CamelCase response

```text
x-am-response-case: camelCase
```

```json
{ "firstName": "JOHN", "lastName": "DOE" }
```

### CapitalCase response

```json
{ "First Name": "JOHN", "Last Name": "DOE" }
```

### ConstantCase response

```json
{ "FIRST_NAME": "JOHN", "LAST_NAME": "DOE" }
```

### DotCase response

```json
{ "first.name": "JOHN", "last.name": "DOE" }
```

### HeaderCase response

```json
{ "First-Name": "JOHN", "Last-Name": "DOE" }
```

### NoCase response

```json
{ "first name": "JOHN", "last name": "DOE" }
```

### ParamCase response

```json
{ "first-name": "JOHN", "last-name": "DOE" }
```

### PascalCase response

```json
{ "FirstName": "JOHN", "LastName": "DOE" }
```

### PathCase response

```json
{ "first/name": "JOHN", "last/name": "DOE" }
```

### SentenceCase response

```json
{ "First name": "JOHN", "Last name": "DOE" }
```

### SnakeCase response

```json
{ "first_name": "JOHN", "last_name": "DOE" }
```

## x-am-response-object-type

Flattens nested objects, such as the ones [deep](https://docs.apimaker.dev/v1/docs/apis-all/query-params/deep.html) produces, into one level with `_` between the names. Default : `no_action`.

### No action

```text
x-am-response-object-type: no_action
```

```json
{ "id": 101, "state_id": { "id": 201, "country_id": { "id": 301, "country_name": "INDIA" }, "state_name": "GUJARAT" }, "city_name": "AHMEDABAD" }
```

### Make flat

```text
x-am-response-object-type: make_flat
```

```json
{ "id": 101, "state_id_id": 201, "state_id_country_id_id": 301, "state_id_country_id_country_name": "INDIA", "state_id_state_name": "GUJARAT", "city_name": "AHMEDABAD" }
```

- Handy for grids, CSV exports and spreadsheets.

## x-am-meta

Adds `meta` to the answer. Default : `false`.

### False

```text
x-am-meta: false
```

### True

```text
x-am-meta: true
```

```json
{
    "data": [ { "id": 301, "country_name": "INDIA" } ],
    "meta": {
        "executionTime": "15ms",
        "executionTimeMS": 15,
        "executionPlan": [],
        "apiAccessGroups": [ { "groupId": "6381b80359bdbd3a87c9abd5", "groupName": "all_permission", "hasAccess": true } ],
        "runBy": [ { "apiCategory": "CUSTOM_APIS", "serverId": "server1", "processId": "…", "workerId": "1", "port": 38246 } ]
    }
}
```

| Key | Meaning |
|---|---|
| `executionTime`, `executionTimeMS` | Time spent in API Maker, without the network. |
| `executionPlan` | The explain plan of MongoDB for the query. |
| `apiAccessGroups` | The groups of the API user and which one granted the call. |
| `runBy` | Which server, process, worker and sandbox ran the code. |

## x-am-internationalization

The name of a language of [i18N Management](https://docs.apimaker.dev/v1/docs/i18/i18.html). Every message of the answer, the messages of API Maker as well as your own from `errorList` and thrown strings, comes back in that language. The value `Default` (or no header) gives the original messages.

```text
x-am-internationalization: Hindi
```

**Default**

```json
{ "code": 400, "message": "Please provide id param value" }
```

**Hindi**

```json
{ "code": 400, "message": "कृपया आईडी पैरामीटर का मान प्रदान करें." }
```

**Chinese simple**

```json
{ "code": 400, "message": "请提供id参数的值" }
```

**Spanish**

```json
{ "code": 400, "message": "Proporcione el valor del parámetro id." }
```

**Japanese**

```json
{ "code": 400, "message": "id パラメータの値を入力してください" }
```

**Urdu**

```json
{ "code": 400, "message": "براہ کرم id پیرامیٹر کی قدر فراہم کریں۔" }
```

- Add a language, change a message, and the next call answers with it : no restart.

## x-am-run-in-sandbox

Which of the sandboxes of the account may run the code of this call (custom API, hooks, events). An account has `sandboxCountForAdmin` sandboxes per API Maker process.

```text
x-am-run-in-sandbox: 0      # any sandbox (default)
x-am-run-in-sandbox: 1      # always the first sandbox
x-am-run-in-sandbox: 2      # one of the first two
x-am-run-in-sandbox: 3      # one of the first three
```

- Pin a call to one sandbox when your code keeps state in memory, such as a connection opened by a [process initializer](https://docs.apimaker.dev/v1/docs/features/process-initializers.html).

## x-am-content-type-response

The format of the answer. Default : `application/json`.

### Application/json

```text
x-am-content-type-response: application/json
```

```json
{ "success": true, "statusCode": 200, "data": [ { "customer_id": 4, "first_name": "JOHNNY", "last_name": "LOLLOBRIGIDA" } ] }
```

### Text/xml

```text
x-am-content-type-response: text/xml
```

```xml
<?xml version='1.0'?>
<root>
    <success>true</success>
    <statusCode>200</statusCode>
    <data>
        <_el>
            <customer_id>4</customer_id>
            <first_name>JOHNNY</first_name>
            <last_name>LOLLOBRIGIDA</last_name>
        </_el>
    </data>
</root>
```

### Text/yaml

```text
x-am-content-type-response: text/yaml
```

```yaml
success: true
statusCode: 200
data:
    - customer_id: 4
      first_name: JOHNNY
      last_name: LOLLOBRIGIDA
```

### Text/plain, text/html, application/octet-stream

```text
x-am-content-type-response: text/plain
```

- The same envelope as text, HTML or bytes. A custom API can also decide the format itself with `g.res.contentType`, see [Content types](https://docs.apimaker.dev/v1/examples/res/contentType/contentType.html).

## x-am-cache-control

For an API with [caching](https://docs.apimaker.dev/v1/docs/features/automatic-caching.html) on. Default : `no_action`.

### No action to cache

```text
x-am-cache-control: no_action
```

- The answer comes from Redis when it is there. The response header `x-am-data-source` says `cache`.

### Reset cache

```text
x-am-cache-control: reset_cache
```

- The API runs against the database and its answer replaces the cached one. `x-am-data-source` says `api`.

## x-am-get-encrypted-data

Encrypts the answer with `encryptionAlgorithmFETransfer` and `secretFETransfer` of the secret, the key you share with your frontend or mobile app. Default : `no_encryption`.

### No encryption

```json
{ "success": true, "statusCode": 200, "data": [ { "customer_id": 53, "first_name": "Deli", "last_name": "Augustus" } ] }
```

### Get only encryption

```text
x-am-get-encrypted-data: get_only_encryption
```

```json
{ "success": true, "statusCode": 200, "data": null, "encryptedData": "U2FsdGVkX1+6qMdb3jXwJAUWH/qlwBq75mtA1kzpWccrNZRAr+CE2c3VtGpkEtVjH==" }
```

### Get data and encryption

```text
x-am-get-encrypted-data: get_data_and_encryption
```

```json
{ "success": true, "statusCode": 200, "data": [ { "customer_id": 53, "first_name": "Deli", "last_name": "Augustus" } ], "encryptedData": "U2FsdGVkX1+6qMdb3jXwJAUWH/qlwBq75mtA1kzpWccrNZRAr+CE2c3VtGpkEtVjH==" }
```

- The client decrypts `encryptedData` with the same algorithm and key (AES, RC4 or TripleDES, as in the secret).

## x-am-encrypted-payload

Tells API Maker that the body is encrypted : `{ "dataEncFE": "…" }`, where `dataEncFE` is `{ data, createdAt }` encrypted with the transfer key of the secret. A payload older than `feTransferDataValidityInSeconds` is refused. With `acceptOnlyEncryptedData: true` in the settings, plain bodies are refused. See [Security features](https://docs.apimaker.dev/v1/docs/features/security-features.html#encrypted-request-payloads).

```text
x-am-encrypted-payload: true
```

## x-am-tenant-username

The tenant of the request, for the APIs of a [multi-tenant](https://docs.apimaker.dev/v1/docs/features/multi-tenant.html) instance : they work on the database of that tenant.

- It names the tenant only. Each multi-tenant instance looks the tenant up in its own tenants table, the entry of the default secret chosen as its **Connection String Multi Tenant**. So one header serves every multi-tenant instance a request or a custom API uses, even when they use different tenants tables.
- It does what naming the tenant in the path does, after the instance name and two colons : `/api/schema/admin/crm::acme/crm/customers`. When a request does both, the tenant of the path is used.
- A tenant the tenants table does not have, or which the `find` of its secret entry leaves out, is refused with 400 : `Unable to find tenant with username 'acme'.`
- An empty value names no tenant : the request works on the structure database.
- A custom API reads the tenant in `g.req.params.tenantUsername`, and passes it on to the APIs it calls with `g.sys.db` and `g.sys.system`. The hooks of the request do the same.
- Custom, system and third party APIs with caching keep their cached answers per tenant.
- A [token of a user](https://docs.apimaker.dev/v1/docs/features/multi-tenant.html#users-of-a-tenant) made with this header works for that tenant only.
- An instance which is not multi-tenant has one database for every tenant : the header does not change the database it uses.

```text
GET /api/schema/admin/crm/crm/customers
x-am-tenant-username: acme
```

## x-am-sandbox-timeout

How long the code of this call (custom API, hooks, events, listeners) may run, in milliseconds. Default : `sandboxReqTimeout` of the [configuration](https://docs.apimaker.dev/v1/docs/am-resources/api-maker-configurations.html), `13000`. When the time is over, the sandbox stops the code and the answer is an error.

```text
x-am-sandbox-timeout: 60000
```

- A custom API can set its own limit in its settings with `customApiTimeoutInSeconds`.

## x-no-compression

Answers of at least `compressThreshold` bytes (51200 by default) are compressed. `true` sends this answer as it is.

- A file sent by a custom API is compressed whatever its size. Streamed answers (the `/stream` APIs) are never compressed.

```text
x-no-compression: true
```

## accept-encoding

The standard header. API Maker picks the first of `gzip`, `br` (Brotli) and `deflate` which the header accepts : a browser sending `gzip, deflate, br` gets gzip, which costs far less CPU than Brotli for nearly the same size. Send `accept-encoding: br` to get Brotli. `identity`, or no header at all, means no compression.

```text
accept-encoding: gzip
```

## Response headers

| Header | Meaning |
|---|---|
| `x-am-data-source` | `cache` when the answer came from Redis, `api` when the API ran. Always `api` for streams. |
| `x-am-request-id` | The id of the request, the same in the logs of API Maker. |
| `content-encoding` | `br`, `gzip` or `deflate` when the answer is compressed. |

## From your code

The same headers go in `headers` of every `g.sys` call :

```typescript
const rows = await g.sys.db.getAll({
    instance: 'mysql8', database: 'inventory', collection: 'customers',
    headers: { 'x-am-response-case': 'camelCase', 'x-am-tenant-username': 'acme' },
});
```
