> For the complete documentation index, see [llms.txt](https://multiset.gitbook.io/multiset/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://multiset.gitbook.io/multiset/basics/credentials.md).

# Credentials

Create credentials to authenticate API's and SDKs once you create new credentials you can download or copy.

Go to **Developer Portal** -> **Credentials** -> **Create New** -> **Enter Name**

You will get the **Client ID** and **Client Secret**.

You can set the scope of each credential at the time of creation

**Query**: Read access to retrieve data and perform Localization queries

**Write**: Create and update access to modify existing Map, MapSet or Object Tracking data

**Delete**: Remove access to permanently delete Account data

{% hint style="warning" %}
Please download or copy credentials immediately after creating them as you can't access them later
{% endhint %}

## How Credentials Work

MultiSet uses an **OAuth 2.0–style client credentials flow** for machine-to-machine (M2M) authentication. Your `clientId` and `clientSecret` are long-lived identifiers for your application; they are exchanged at runtime for a short-lived **Bearer access token (JWT)** that authorizes individual API calls.

<figure><img src="/files/vF0OFx6qXSLfOImXHkgF" alt="MultiSet credentials authentication flow"><figcaption><p>Client Credentials → Bearer JWT → Authenticated API request</p></figcaption></figure>

### Step-by-step

1. **Create credentials in the Developer Portal.** A `clientId` and `clientSecret` are generated and bound to your account, with the scopes you select (Query / Write / Delete). The secret is shown once — store it somewhere safe (env vars, a secrets manager, server-side config). MultiSet does not store a recoverable copy.
2. **Exchange credentials for an access token.** Your application sends a `POST` request to `https://api.multiset.ai/v1/m2m/token` with an `Authorization: Basic base64(clientId:clientSecret)` header. The endpoint validates that the client is active, the secret matches, and the owning account is verified and active.
3. **Receive a Bearer token.** On success, the response contains a signed JWT and an `expiresOn` timestamp. Tokens are valid for **30 minutes** from issue.
4. **Call MultiSet APIs.** Attach the token to every request as `Authorization: Bearer <token>`. This applies to REST endpoints (Map, MapSet, Localization, Object Tracking) and to SDK calls that route through the MultiSet cloud.
5. **Per-request validation.** For each API call the backend verifies the token signature and expiry, checks that the credential's scope permits the requested route and method, and enforces the CORS allowlist configured for your account.
6. **Refresh before expiry.** When the token expires (or you receive a `401`), repeat step 2 to obtain a fresh one. There is no separate refresh-token flow — re-authenticate with `clientId` + `clientSecret`.

### Scopes and authorization

Scopes are evaluated on every request. A token issued from a credential created with only the **Query** scope cannot perform write or delete operations, even if the route exists — the API will respond with `403 Forbidden`. Choose the minimum scope your integration needs, and create separate credentials for read-only services (e.g. a public-facing localization client) versus tools that manage map data.

### Security best practices

* **Never embed `clientSecret` in a shipped mobile app, public website, or git repository.** Treat it like a password.
* For server-side and back-office tools, store the secret in a secrets manager or environment variable and exchange it for a token at runtime.
* For browser-based experiences (e.g. WebXR demos), prefer a thin backend proxy that holds the secret and returns short-lived tokens to the client. Direct in-browser exchange is convenient for prototyping but exposes the secret to anyone who views the page source.
* **Rotate credentials** if you suspect exposure. Deactivate or delete the old credential in the Developer Portal — existing tokens issued from it remain valid until they expire (max 30 minutes), but no new tokens can be issued.
* **Restrict by origin.** Configure your CORS allowlist so that browser requests can only be made from the domains you control. See [Configuring Allowed Domains (CORS)](/multiset/basics/credentials/configuring-allowed-domains-cors.md).
* **Use distinct credentials per environment** (dev / staging / prod) so you can rotate or revoke one without affecting the others.

### Where to use the token

| Surface                   | How credentials are used                                                                                        |
| ------------------------- | --------------------------------------------------------------------------------------------------------------- |
| REST API                  | Exchange `clientId`/`clientSecret` for a token, then send `Authorization: Bearer <token>` on every request.     |
| Unity SDK / Quest SDK     | Configure `clientId` and `clientSecret` in the SDK; the SDK performs the token exchange and refresh internally. |
| iOS / Android native SDKs | Same as Unity — pass credentials to the SDK config and it handles token lifecycle.                              |

For the full token-endpoint reference and copy-paste code samples, see [Authentication](/multiset/basics/rest-api-docs/authentication.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://multiset.gitbook.io/multiset/basics/credentials.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.
