# Raw service tokens and refresh
URL: https://musicapi.com/docs/connect-users/raw-tokens-and-refresh.md

> Read a connected user's own music-service access token to call the service yourself, from your backend or once from an app, and force a token refresh.

Product: MusicAPI Core. Section: Connect your users.

MusicAPI keeps each user's music-service tokens and renews them for you. Most integrations never touch them. Read them only to call a service endpoint that MusicAPI does not cover.

> **Raw tokens are personal data:** An access token opens the user's music account. Read it on your backend, keep it out of logs, and do not store it longer than you need it.

## From your backend (Client Secret)

[`GET /public/integrations/user/{integrationUserUUID}`](https://musicapi.com/docs/reference/get-integration-user.md) with Basic authentication returns `authData`.

```bash
curl "https://api.musicapi.com/public/integrations/user/3f0b8c1e-6a4d-4c7a-9a55-2f1e7d9b0c11" \
  -u "$MUSICAPI_CLIENT_ID:$MUSICAPI_CLIENT_SECRET"
```

```json
{
  "integrationUser": {
    "uuid": "3f0b8c1e-6a4d-4c7a-9a55-2f1e7d9b0c11",
    "integrationUserId": "mica.nowak",
    "name": "Mica Nowak",
    "email": "mica@example.com",
    "imageUrl": "https://images.example.com/mica.jpg",
    "country": "PL",
    "authData": { "accessToken": "BQD…" },
    "authDataExpiresAt": 1792137600000
  },
  "integration": { "type": "spotify" }
}
```

- `authData` holds the service's credentials **without the refresh token**. The fields depend on the service.
- `authDataExpiresAt` is when the access token expires, in milliseconds since the epoch.
- When the token expires within one minute, MusicAPI renews it before it answers.

## From an app without a backend (one-time token)

1. **Ask for a token**

   Add `requestOneTimeToken=true` to the [sign-in URL](https://musicapi.com/docs/connect-users/start-sign-in.md).
2. **Read it from the callback**

   The decoded `data64` holds `oneTimeToken`.
3. **Spend it at once**

   Call the connected-user endpoint with `Authorization: Token <oneTimeToken>` within 30 seconds.

```url
https://app.musicapi.com/{slug}?returnUrl={returnUrl}&requestOneTimeToken=true
```

```bash
curl "https://api.musicapi.com/public/integrations/user/3f0b8c1e-6a4d-4c7a-9a55-2f1e7d9b0c11" \
  -H "Authorization: Token e50cc5e7-254a-4cff-a000-457ae53a059d"
```

The one-time token is bound to the sign-in it came from. For another connected user it answers `403`. You can also pass it as `?oneTimeToken=` to [`GET /public/integrations/auth/{authModelUUID}`](https://musicapi.com/docs/reference/get-sign-in-result.md).

### Attach-only tokens for browser sign-ins

You can keep the music-service tokens out of the browser. In the dashboard, open **API & webhooks** and turn on **Browser logins can only attach**. The setting is off by default.

When it is on, the `oneTimeToken` of a sign-in that returns to a web page (an `http` or `https` `returnUrl`) does not read `authData`. [`GET /public/integrations/user/{integrationUserUUID}`](https://musicapi.com/docs/reference/get-integration-user.md) and [`GET /public/integrations/auth/{authModelUUID}`](https://musicapi.com/docs/reference/get-sign-in-result.md) answer that token without `authData` and `authDataExpiresAt`. The token still proves the sign-in. Read the raw tokens from your backend with your Client Secret.

A sign-in that returns to a native app (a custom scheme such as `myapp://`) keeps the full token.

## Force a refresh

[`POST /public/integrations/refreshAuthToken`](https://musicapi.com/docs/reference/refresh-integration-user-token.md) renews the tokens of one user now, for example after the service told you the token is no longer valid.

```bash
curl -X POST "https://api.musicapi.com/public/integrations/refreshAuthToken" \
  -u "$MUSICAPI_CLIENT_ID:$MUSICAPI_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"integrationUserUUID": "3f0b8c1e-6a4d-4c7a-9a55-2f1e7d9b0c11"}'
```

- With Basic the answer holds the new `authData`. Other credentials get the profile only.
- When the service refuses the renewal, the answer is `401`. The user must [sign in again](https://musicapi.com/docs/get-started/rate-limits-and-errors.md#the-user-must-sign-in-again-412).

You never need this for MusicAPI's own library calls: they renew an expired token by themselves.
