> For the complete documentation index, see [llms.txt](https://docs.carto.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.carto.com/carto-for-developers/reference/hosted-apps/runtime-and-authentication.md).

# Runtime and authentication

How a hosted app is opened, the carto-info.json contract, sessions, sharing and versions

{% hint style="info" %}
**Private Preview:** Hosted Apps is available to selected accounts during its Private Preview. To request access, contact your CARTO representative.
{% endhint %}

A hosted app has no server of its own. CARTO serves its files to signed-in users, and gives the app the credentials of the user who opened it.

## Opening an app

Every file under `/app/<slug>/` requires an **app session**. When someone opens the app URL without one, CARTO signs them in, with your organization's SSO when it is configured, and then opens the app at its start page. The path, query string and fragment of the original URL are not kept.

Only a page load can start a session, so users must open the app through its URL. Loading the app's files from another page does not work.

A signed-in user the app is not shared with gets `403`. A slug that does not exist in their organization returns `404`.

### The app session

* It is a cookie, `httpOnly` and scoped to `/app`, so the app's JavaScript cannot read it and it is not sent to the rest of the workspace.
* It carries the user's access token, encrypted. The token is not exposed in URLs, browser history or logs.
* It lasts **up to one hour**, and never longer than the access token.

Requests for the app's files and for `carto-info.json` are authenticated by this cookie only. An `Authorization` header sent with them is ignored.

### Renewing the session

When the session ends, `carto-info.json` returns `401`, and other files of the app can no longer be loaded. The app can keep using the access token it already has until that token expires (`expiresAt`).

To renew the session, navigate the browser to `/app/_session?slug=<slug>`, as shown in [Hosting your application in CARTO](/carto-for-developers/guides/build-a-hosted-application.md). CARTO signs the user in again, without any prompt while they are still logged in to CARTO, and reopens the app at its start page. Because it is a full page load, save any state the user would lose first. Renew when `carto-info.json` or a CARTO API returns `401`.

## The `carto-info.json` contract

The app fetches `./carto-info.json`, relative to its own `/app/<slug>/` path. CARTO generates it for each user and never caches it.

```json
{
  "schemaVersion": 1,
  "accessToken": "eyJ...",
  "apiBaseUrl": "https://gcp-us-east1.api.carto.com",
  "expiresAt": 1789000000,
  "user": {
    "id": "auth0|...",
    "accountId": "ac_...",
    "email": "user@example.com",
    "username": "user",
    "picture": "https://lh3.googleusercontent.com/..."
  }
}
```

| Field           | Type             | Always present | Description                                                                                                                         |
| --------------- | ---------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `schemaVersion` | integer          | Yes            | Version of this contract, currently `1`. It changes only if the contract changes in a breaking way.                                 |
| `accessToken`   | string           | Yes            | The access token of the signed-in user, to send as `Authorization: Bearer`. No token is created for the app.                        |
| `apiBaseUrl`    | string           | Yes            | The CARTO API base URL. Append the API path to it, for example `/v3/sql/...`.                                                       |
| `expiresAt`     | integer          | No             | When the access token expires, in Unix seconds. The app session can end earlier; see [Renewing the session](#renewing-the-session). |
| `user`          | object or `null` | Yes            | The signed-in user. See [the `user` object](#the-user-object).                                                                      |

Other fields may be present. Ignore the ones you do not use.

| Status | Meaning                                                     |
| ------ | ----------------------------------------------------------- |
| `200`  | The contract above.                                         |
| `401`  | No valid app session. Renew it as described above.          |
| `403`  | The user is signed in, but the app is not shared with them. |
| `404`  | There is no app with this slug in the user's organization.  |

Two rules follow from this file being generated for each user:

* **`carto-info.json` is a reserved filename.** A bundle cannot include a file with that name at its root.
* **Fetch it relative to the app path**, as `./carto-info.json`, and do not cache it. An absolute `/carto-info.json` does not resolve.

### The `user` object

| Field       | Type             | Description                                                                                                                                                                                                                                                             |
| ----------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`        | string           | The user's CARTO id.                                                                                                                                                                                                                                                    |
| `accountId` | string           | The id of the organization the user belongs to.                                                                                                                                                                                                                         |
| `email`     | string or `null` | The user's email. `null` when the token carries no email.                                                                                                                                                                                                               |
| `username`  | string or `null` | The user's CARTO username. It is derived from the email, not a display name. `null` when unknown.                                                                                                                                                                       |
| `picture`   | string or `null` | The URL of the user's avatar, on a host the app's [Content Security Policy](/carto-for-developers/reference/hosted-apps/bundle-requirements-and-limits.md#the-content-security-policy) allows, so the app can display it. `null` when CARTO has no avatar for the user. |

## The app runs as the signed-in user

* **Permissions are the user's.** The app can see and do what that user can see and do in CARTO, through the same APIs, and nothing more.
* **Usage is the user's.** The app's API requests are the user's requests, and consume your organization's quota like any other request from that user.
* **There are no app credentials.** No token, client or service identity is created for a hosted app, so there is nothing to rotate.
* **The bundle is visible to its users.** Anyone who can open the app can read its files, so a bundle cannot hold a secret. Keep SQL in [Named Sources](/carto-for-developers/reference/hosted-apps/app-manifest.md#sources), and never include a credential in the bundle.

## Sharing

Sharing works as it does for maps and workflows.

| `carto app share` flag | Who can open the app                              |
| ---------------------- | ------------------------------------------------- |
| `--private`            | Only the owner.                                   |
| `--org`                | Everyone in the organization.                     |
| `--group <ids>`        | The listed groups. Can be combined with `--user`. |
| `--user <ids>`         | The listed users. Can be combined with `--group`. |

* A newly deployed app is private.
* Each `carto app share` call **replaces** the previous sharing settings.
* Redeploying an app does not change its sharing.
* Only the owner can redeploy, share, roll back or delete the app. Sharing an app lets users open it, not change it.

## Versions

| Property       | Behavior                                                                                                                                                       |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Label          | Set with `carto app deploy --version <label>`. Must match `/^(?!.*\.\.)[a-zA-Z0-9.:_-]{1,64}$/`: 1 to 64 letters, digits, `.`, `:`, `_` and `-`, with no `..`. |
| Default label  | The UTC date and time of the deploy.                                                                                                                           |
| Immutability   | A deployed version cannot be changed. Deploying an existing label again fails.                                                                                 |
| Active version | Exactly one version is served at a time. Each deploy activates the version it creates.                                                                         |
| Rollback       | `carto app rollback <slug> <version>` makes a previously deployed version the active one.                                                                      |

A rollback only changes the files that are served. The URL, the sharing settings and the app's Named Sources stay as they were. If an older bundle needs different Named Sources, deploy it again instead of rolling back to it.

Users who already have the app open keep the files their browser loaded until they reload the page.

## Related

* [App manifest (`carto.json`)](/carto-for-developers/reference/hosted-apps/app-manifest.md): the Named Sources the app declares.
* [Bundle requirements and limits](/carto-for-developers/reference/hosted-apps/bundle-requirements-and-limits.md): client-side routing, response headers and the CSP.
* [Authentication methods](/carto-for-developers/key-concepts/authentication-methods.md): how this compares with API Access Tokens and OAuth.


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.carto.com/carto-for-developers/reference/hosted-apps/runtime-and-authentication.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
