# `Magpie.Auth.Token`
[🔗](https://github.com/alexcassol/magpie/blob/v0.3.1/lib/magpie/auth/token.ex#L1)

An OAuth 2 token set returned by Dropbox's `/oauth2/token` endpoint.

  * `access_token` — the short-lived token used to authenticate API calls
  * `refresh_token` — the long-lived token used to mint new access tokens.
    Only returned by the code exchange; refresh responses leave it `nil`,
    since Dropbox does not rotate refresh tokens (keep the original one)
  * `expires_at` — absolute expiry, computed from Dropbox's `expires_in`
  * `scope` — space-separated scopes granted to the token, when present
  * `account_id` / `uid` — the Dropbox account the token belongs to
    (code exchange only)

# `t`

```elixir
@type t() :: %Magpie.Auth.Token{
  access_token: String.t() | nil,
  account_id: String.t() | nil,
  expires_at: DateTime.t() | nil,
  refresh_token: String.t() | nil,
  scope: String.t() | nil,
  uid: String.t() | nil
}
```

# `fresh?`

```elixir
@spec fresh?(t(), non_neg_integer()) :: boolean()
```

Returns `true` when the token is usable for at least `margin` more seconds.

A token without an `expires_at` is never considered fresh — its expiry is
unknown, so it is safer to refresh it.

    iex> token = %Magpie.Auth.Token{access_token: "sl.ABC", expires_at: DateTime.add(DateTime.utc_now(), 3600)}
    iex> Magpie.Auth.Token.fresh?(token, 300)
    true
    iex> Magpie.Auth.Token.fresh?(%Magpie.Auth.Token{}, 300)
    false

# `from_response`

```elixir
@spec from_response(map()) :: t()
```

Builds a token from a decoded `/oauth2/token` response body.

`expires_in` (seconds from now) is turned into an absolute `expires_at`.

    iex> body = %{"access_token" => "sl.ABC", "expires_in" => 14_400, "token_type" => "bearer"}
    iex> token = Magpie.Auth.Token.from_response(body)
    iex> token.access_token
    "sl.ABC"
    iex> DateTime.diff(token.expires_at, DateTime.utc_now()) > 14_000
    true

---

*Consult [api-reference.md](api-reference.md) for complete listing*
