> For the complete documentation index, see [llms.txt](https://docs.tumbler.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tumbler.app/subscription-contract/metadata.md).

# Metadata

## Who this is for

Providers who control backend and client behavior through meta fields in the response body or HTTP headers.

## How metadata is passed and prioritized

* In the body: meta lines `#key: value` in text lists or a `meta` object in JSON.
* In headers: `Support-URL`, `Manage-URL`, `Hide-Settings`, `Subscription-Userinfo`, `X-Subscription-New-URL`, `X-Subscription-Mirrors`, and other equivalent `X-Subscription-*`/short names (case-insensitive).
* **Priority:** headers override metadata from the body. If the same field is present in both places, the header value is used.

## What counts as metadata

Metadata is additional control data around an existing subscription. It does not replace the VLESS/Xray/sing-box configs themselves.

A minimal working response may contain no metadata at all: valid `vless://...` lines or JSON `links`/`nodes` are enough. Add metadata after the basic import already works.

## Provider control keys

| Key                                                      | Type / default                                                                               | Example                                                   | Effect                                                                                                                                                                                                                                                                  |
| -------------------------------------------------------- | -------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `support-url`                                            | string URL, empty = no link                                                                  | `https://help.example.com`                                | Support button/link in the UI and `/v1/providers`; helps the user contact support.                                                                                                                                                                                      |
| `manage-url`                                             | string URL, empty = no link                                                                  | `https://account.example.com/billing`                     | Manage button/link for account or billing; shown to the user and in `/v1/providers`.                                                                                                                                                                                    |
| `mirrors`                                                | list of full `http/https` URLs without `userinfo` (`username:password@`), empty = no mirrors | `https://m1.example.com/sub, https://m2.example.com/sub`  | Used by the refresh cycle as fallback after the primary URL; order is preserved, duplicates are removed.                                                                                                                                                                |
| `new-url`                                                | full URL, optional                                                                           | `https://new.example.com/sub`                             | Wins over `new-domain`. Becomes the new canonical link: the backend updates the subscription through it and sends it to the client.                                                                                                                                     |
| `new-domain`                                             | domain without scheme/path, optional                                                         | `new.example.com`                                         | Changes only the host of the canonical URL for future updates when `new-url` is not set. Use it when the path stays the same.                                                                                                                                           |
| `hide-settings`                                          | bool, default `false`                                                                        | `true`                                                    | Hides part of the manual settings in the UI (aggregated with OR across provider snapshots).                                                                                                                                                                             |
| `profile-title` (`profile_title` alias)                  | string, default empty                                                                        | `Premium NL`                                              | Profile title shown by the client as the subscription display name. Accepted in meta and headers as `profile-title` and `profile_title` (case-insensitive).                                                                                                             |
| `installation-limit`                                     | int >= 0, default `0` (= unlimited)                                                          | `3`                                                       | Limits the number of active installations. Exceeding it returns `INSTALLATION_LIMIT_EXCEEDED` when issuing a new installation.                                                                                                                                          |
| `connection-limit`                                       | int >= 0, default `0` (= unlimited)                                                          | `2`                                                       | Concurrent VPN connection limit per installation. `1` fixes one connection; values >= 2 apply only if the provider/installation plan includes this capability (see the [feature matrix](/features/overview.md)). When exceeded, new sessions are blocked by the server. |
| `balancer-method`                                        | `ping` or `connections`, empty = off                                                         | `ping`                                                    | Enables server-side node reordering: leader is selected by RTT (`ping`) or load (`connections`). Requires metrics collection.                                                                                                                                           |
| `capabilities`                                           | array/string list, empty = no paid capabilities                                              | `["advanced_connection_control"]`                         | Declaration of paid features approved for the provider. ACC uses this together with `acc-enabled` and `acc-*` fields.                                                                                                                                                   |
| `subscription-userinfo`                                  | string `upload=<bytes>; download=<bytes>; total=<bytes>; expire=<unix-seconds>`              | `upload=123; download=456; total=1024; expire=1800000000` | Unified way to pass traffic usage/limit and subscription expiry.                                                                                                                                                                                                        |
| `upload` / `download` / `total` / `expire` (`expire-at`) | int64 >= 0                                                                                   | `upload=123`, `expire-at=1800000000`                      | Same quota/expiry data as separate keys in `meta`, body lines, or alias headers.                                                                                                                                                                                        |

### URL migrations

* `new-url` always wins over `new-domain`. If both are present, only `new-url` is used.
* If `new-url` is present, the canonical URL is saved with it; future refresh requests and subscription updates use the new address. The backend also treats its host as `new-domain` by default, so the provider does not need to set anything else.
* `new-domain` changes only the host of the canonical URL, preserving the path/scheme of the original final URL; it is used only when `new-url` is empty.
* If both fields are empty, the backend stays on the current canonical URL.

### Mirrors

* Mirrors are used when the primary request (preferred + canonical candidates) returns an error or HTTP 4xx/5xx. After all primary candidates fail, the backend adds mirrors and tries them in order without extra primary retries.
* If the chain is already in skip-primary mode (circuit breaker), the first mirror is tried immediately.
* Format: comma-separated list in headers, array of strings in meta.
* Put the most reliable/fastest mirrors first; all URLs must be absolute and must not contain `userinfo` (`username:password@` is not allowed in URLs).

### What the user sees

* `support-url` / `manage-url` are shown as buttons/links in the provider card.
* `hide-settings` hides part of the manual settings (connection parameters) in the client.
* `installation-limit` / `connection-limit` affect connection permission: when exceeded, new installations or sessions are blocked by the server.
* `subscription-userinfo`/`upload`/`download`/`total`/`expire` let the client show subscription expiry and traffic statistics.

## Examples

### Headers only

```
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Support-URL: https://help.example.com
Manage-URL: https://account.example.com
X-Subscription-New-URL: https://new.example.com/sub
X-Subscription-Mirrors: https://m1.example.com/sub, https://m2.example.com/sub
Hide-Settings: true
Profile-Title: Premium NL
Profile_Title: Premium NL
Connection-Limit: 2
Subscription-Userinfo: upload=123456; download=654321; total=10737418240; expire=1800000000

vless://11111111-1111-1111-1111-111111111111@edge.example.com:443#Edge
```

All listed keys are read from headers and override body values if present.

### Body meta

```json
{
  "links": [
    "vless://aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa@a.example.com:443#A",
    "vless://bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb@b.example.com:8443#B"
  ],
  "meta": {
    "support-url": "https://help.example.com",
    "manage-url": "https://account.example.com/billing",
    "mirrors": ["https://m1.example.com/sub", "https://m2.example.com/sub"],
    "new-domain": "new.example.com",
    "hide-settings": true,
    "profile-title": "Premium NL",
    "profile_title": "Premium NL",
    "installation-limit": 1,
    "connection-limit": 2,
    "capabilities": ["advanced_connection_control"],
    "balancer-method": "ping",
    "subscription-userinfo": "upload=123456; download=654321; total=10737418240; expire=1800000000",
    "upload": 123456,
    "download": 654321,
    "total": 10737418240,
    "expire-at": 1800000000
  }
}
```

## See also

* [subscription/response-formats.md](/subscription-contract/response-formats.md)
* [operations/mirrors-and-migration.md](/after-first-launch/mirrors-and-migration.md)
* [features/overview.md](/features/overview.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.tumbler.app/subscription-contract/metadata.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
