# `Hunter`
[🔗](https://github.com/milmazz/hunter/blob/v0.8.0/lib/hunter.ex#L1)

An Elixir client for the Mastodon API

# `accept_follow_request`

```elixir
@spec accept_follow_request(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.Relationship.t()
```

Accepts a follow request

## Parameters

  * `conn` - connection credentials
  * `id` - follow request id

# `accept_notification_request`

```elixir
@spec accept_notification_request(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  boolean()
```

Accept a notification request, so future notifications from the account
are delivered normally

## Parameters

  * `conn` - connection credentials
  * `id` - notification request identifier

# `accept_notification_requests`

```elixir
@spec accept_notification_requests(Hunter.Client.t(), [String.t() | non_neg_integer()]) ::
  boolean()
```

Accept multiple notification requests

## Parameters

  * `conn` - connection credentials
  * `ids` - notification request identifiers

# `account`

```elixir
@spec account(Hunter.Client.t(), String.t() | non_neg_integer()) :: Hunter.Account.t()
```

Retrieve account

## Parameters

  * `conn` - connection credentials
  * `id` - account identifier

# `account_endorsements`

```elixir
@spec account_endorsements(
  Hunter.Client.t(),
  String.t() | non_neg_integer(),
  Keyword.t()
) :: [
  Hunter.Account.t()
]
```

Retrieve the accounts a given account is featuring on their profile

## Parameters

  * `conn` - connection credentials
  * `id` - account identifier
  * `options` - option list

## Options

  * `max_id` - get a list of endorsements with id less than or equal this value
  * `since_id` - get a list of endorsements with id greater than this value
  * `limit` - maximum number of endorsements to get

# `account_featured_tags`

```elixir
@spec account_featured_tags(Hunter.Client.t(), String.t() | non_neg_integer()) :: [
  Hunter.FeaturedTag.t()
]
```

Retrieve the hashtags an account is featuring on their profile

## Parameters

  * `conn` - connection credentials
  * `id` - account identifier

# `account_lists`

```elixir
@spec account_lists(Hunter.Client.t(), String.t() | non_neg_integer()) :: [
  Hunter.List.t()
]
```

Retrieve the user's lists that contain a given account

## Parameters

  * `conn` - connection credentials
  * `account_id` - account identifier

# `accounts_by_ids`

```elixir
@spec accounts_by_ids(Hunter.Client.t(), [String.t() | non_neg_integer()]) :: [
  Hunter.Account.t()
]
```

Retrieve multiple accounts by id

## Parameters

  * `conn` - connection credentials
  * `ids` - list of account identifiers

# `add_accounts_to_list`

```elixir
@spec add_accounts_to_list(Hunter.Client.t(), String.t() | non_neg_integer(), [
  String.t() | non_neg_integer()
]) :: boolean()
```

Add accounts to a list; the user must be following each of them

## Parameters

  * `conn` - connection credentials
  * `id` - list identifier
  * `account_ids` - account identifiers to add

# `add_keyword_to_filter`

```elixir
@spec add_keyword_to_filter(
  Hunter.Client.t(),
  String.t() | non_neg_integer(),
  String.t(),
  Keyword.t()
) :: Hunter.FilterKeyword.t()
```

Add a keyword to a filter

## Parameters

  * `conn` - connection credentials
  * `filter_id` - filter identifier
  * `keyword` - the phrase to be matched against
  * `options` - option list

## Options

  * `whole_word` - whether the keyword should consider word boundaries

# `add_status_to_filter`

```elixir
@spec add_status_to_filter(
  Hunter.Client.t(),
  String.t() | non_neg_integer(),
  String.t() | non_neg_integer()
) :: Hunter.FilterStatus.t()
```

Add a status to a filter group

## Parameters

  * `conn` - connection credentials
  * `filter_id` - filter identifier
  * `status_id` - status identifier

# `authorization_url`

```elixir
@spec authorization_url(Hunter.Application.t(), String.t(), Keyword.t()) :: String.t()
```

Build the URL to send the user to for authorization (`GET /oauth/authorize`)

## Parameters

  * `app` - application details, see: `Hunter.create_app/5`
  * `base_url` - API base url, default: `https://mastodon.social`
  * `opts` - optional params

## Options

  * `redirect_uri` - overrides the app's registered redirect URI
  * `scope` - space-separated scopes, defaults to the app's scopes
  * `code_challenge` / `code_challenge_method` - PKCE params, see
    `generate_pkce/0`
  * `state` - opaque value returned to your redirect URI unchanged
  * `force_login` - forces re-login when `true`
  * `lang` - ISO 639-1 language code for the authorization form

Builds a URL only; performs no request.

# `block`

```elixir
@spec block(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.Relationship.t()
```

Block a user

## Parameters

  * `conn` - connection credentials
  * `id` - user identifier

# `block_domain`

```elixir
@spec block_domain(Hunter.Client.t(), String.t()) :: boolean()
```

Block a domain

## Parameters

  * `conn` - connection credentials
  * `domain` - domain to block

# `blocked_domains`

```elixir
@spec blocked_domains(Hunter.Client.t(), Keyword.t()) :: [String.t()]
```

Fetch user's blocked domains

## Parameters

  * `conn` - connection credentials
  * `options` - option list

## Options

  * `max_id` - get a list of blocks with id less than or equal this value
  * `since_id` - get a list of blocks with id greater than this value
  * `limit` - maximum number of blocks to get, default: 40, max: 80

# `blocks`

```elixir
@spec blocks(Hunter.Client.t(), Keyword.t()) :: [Hunter.Account.t()]
```

Retrieve user's blocks

## Parameters

  * `conn` - connection credentials

## Options

  * `max_id` - get a list of blocks with id less than or equal this value
  * `since_id` - get a list of blocks with id greater than this value
  * `limit` - maximum number of blocks to get, default: 40, max: 80

# `bookmark`

```elixir
@spec bookmark(Hunter.Client.t(), String.t() | non_neg_integer()) :: Hunter.Status.t()
```

Bookmark a status

## Parameters

  * `conn` - connection credentials
  * `id` - status identifier

# `bookmarks`

```elixir
@spec bookmarks(Hunter.Client.t(), Keyword.t()) :: [Hunter.Status.t()]
```

Fetch the user's bookmarked statuses

## Parameters

  * `conn` - connection credentials
  * `options` - option list

## Options

  * `max_id` - get a list of bookmarks with id less than or equal this value
  * `since_id` - get a list of bookmarks with id greater than this value
  * `min_id` - get a list of bookmarks with id greater than this value,
    immediately newer
  * `limit` - maximum number of bookmarks to get, default: 20, max: 40

# `clear_notification`

```elixir
@spec clear_notification(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  boolean()
```

Dismiss a single notification

## Parameters

  * `conn` - connection credentials
  * `id` - notification id

# `clear_notifications`

```elixir
@spec clear_notifications(Hunter.Client.t()) :: boolean()
```

Deletes all notifications from the Mastodon server for the authenticated user

## Parameters

  * `conn` - connection credentials

# `create_app`

```elixir
@spec create_app(
  String.t(),
  String.t() | [String.t()],
  [String.t()],
  nil | String.t(),
  Keyword.t()
) :: Hunter.Application.t() | no_return()
```

Register a new OAuth client app on the target instance

## Parameters

  * `name` - name of your application
  * `redirect_uris` - where the user should be redirected after
    authorization; a single URI or a list of URIs (Mastodon 4.3+),
    default: `urn:ietf:wg:oauth:2.0:oob` (no redirect)
  * `scopes` - scope list, see the scope section for more details, default: `read`
  * `website` - URL to the homepage of your app, default: `nil`
  * `options` - option list

## Scopes

  * `read` - read data
  * `write` - post statuses and upload media for statuses
  * `follow` - follow, unfollow, block, unblock

Multiple scopes can be requested during the authorization phase with the `scope` query param

## Options

  * `save?` - persists your application information to a file, so, you can use
    them later. default: `false`
  * `api_base_url` - specifies if you want to register an application on a
    different instance. default: `https://mastodon.social`

## Examples

    iex> Hunter.create_app("hunter", "urn:ietf:wg:oauth:2.0:oob", ["read", "write", "follow"], nil, [save?: true, api_base_url: "https://example.com"])
    %Hunter.Application{client_id: "1234567890",
     client_secret: "1234567890",
     id: "1234"}

# `create_filter`

```elixir
@spec create_filter(Hunter.Client.t(), String.t(), [String.t()], Keyword.t()) ::
  Hunter.Filter.t()
```

Create a new filter

## Parameters

  * `conn` - connection credentials
  * `title` - the name of the filter group
  * `context` - contexts in which the filter is applied, list of:
    `home`, `notifications`, `public`, `thread`, `account`
  * `options` - option list

## Options

  * `filter_action` - action to take when a status matches the filter, one
    of: `warn`, `hide`, `blur`; default: `warn`
  * `expires_in` - seconds from now the filter should expire, `nil` to
    never expire
  * `keywords_attributes` - list of maps with `keyword` and `whole_word`
    keys, the keywords to add to the newly-created filter

# `create_list`

```elixir
@spec create_list(Hunter.Client.t(), String.t(), Keyword.t()) :: Hunter.List.t()
```

Create a new list

## Parameters

  * `conn` - connection credentials
  * `title` - the title of the list
  * `options` - option list

## Options

  * `replies_policy` - which replies should be shown in the list, one of:
    `followed`, `list`, `none`; default: `list`
  * `exclusive` - whether members of the list are removed from the home
    timeline

# `create_push_subscription`

```elixir
@spec create_push_subscription(Hunter.Client.t(), map(), map()) ::
  Hunter.WebPushSubscription.t()
```

Subscribe to Web Push notifications; each access token can have exactly
one subscription, and creating a new one replaces it

## Parameters

  * `conn` - connection credentials
  * `subscription` - map with `endpoint`, `keys` (`p256dh` and `auth`)
    and optionally `standard`
  * `data` - optional map with `alerts` and `policy`

# `create_status`

```elixir
@spec create_status(Hunter.Client.t(), String.t(), Keyword.t()) ::
  Hunter.Status.t() | Hunter.ScheduledStatus.t() | no_return()
```

Create new status

## Parameters

  * `conn` - connection credentials
  * `status` - text of the status
  * `options` - option list

## Options

  * `in_reply_to_id` - local ID of the status you want to reply to
  * `media_ids` - list of media IDs to attach to the status (maximum: 4)
  * `sensitive` - whether the media of the status is NSFW
  * `spoiler_text` - text to be shown as a warning before the actual content
  * `visibility` - either `direct`, `private`, `unlisted` or `public`
  * `language` - ISO 639-1 language code for the status
  * `poll` - map with `options` (list of choices) and `expires_in`
    (seconds); optional: `multiple`, `hide_totals`
  * `quoted_status_id` - ID of a status to quote
  * `scheduled_at` - ISO 8601 datetime (at least 5 minutes ahead) at which
    the status should be published; the call returns a
    `Hunter.ScheduledStatus` instead of a `Hunter.Status`
  * `idempotency_key` - unique string sent as the `Idempotency-Key` header
    to prevent duplicate submissions

# `delete_media`

```elixir
@spec delete_media(Hunter.Client.t(), String.t() | non_neg_integer()) :: boolean()
```

Delete a media attachment that is not currently attached to a status

## Parameters

  * `conn` - connection credentials
  * `id` - attachment identifier

# `delete_push_subscription`

```elixir
@spec delete_push_subscription(Hunter.Client.t()) :: boolean()
```

Remove the Web Push subscription tied to the access token

## Parameters

  * `conn` - connection credentials

# `destroy_filter`

```elixir
@spec destroy_filter(Hunter.Client.t(), String.t() | non_neg_integer()) :: boolean()
```

Delete a filter

## Parameters

  * `conn` - connection credentials
  * `id` - filter identifier

# `destroy_filter_keyword`

```elixir
@spec destroy_filter_keyword(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  boolean()
```

Remove a keyword from a filter

## Parameters

  * `conn` - connection credentials
  * `id` - filter keyword identifier

# `destroy_filter_status`

```elixir
@spec destroy_filter_status(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  boolean()
```

Remove a status from a filter group

## Parameters

  * `conn` - connection credentials
  * `id` - status filter identifier

# `destroy_list`

```elixir
@spec destroy_list(Hunter.Client.t(), String.t() | non_neg_integer()) :: boolean()
```

Delete a list

## Parameters

  * `conn` - connection credentials
  * `id` - list identifier

# `destroy_status`

```elixir
@spec destroy_status(Hunter.Client.t(), String.t() | non_neg_integer()) :: boolean()
```

Destroy status

## Parameters

  * `conn` - connection credentials
  * `id` - status identifier

# `dismiss_notification_group`

```elixir
@spec dismiss_notification_group(Hunter.Client.t(), String.t()) :: boolean()
```

Dismiss a notification group

## Parameters

  * `conn` - connection credentials
  * `group_key` - notification group key

# `dismiss_notification_request`

```elixir
@spec dismiss_notification_request(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  boolean()
```

Dismiss a notification request, removing it and its filtered notifications

## Parameters

  * `conn` - connection credentials
  * `id` - notification request identifier

# `dismiss_notification_requests`

```elixir
@spec dismiss_notification_requests(Hunter.Client.t(), [
  String.t() | non_neg_integer()
]) :: boolean()
```

Dismiss multiple notification requests, removing them and their filtered
notifications

## Parameters

  * `conn` - connection credentials
  * `ids` - notification request identifiers

# `edit_status`

```elixir
@spec edit_status(
  Hunter.Client.t(),
  String.t() | non_neg_integer(),
  String.t(),
  Keyword.t()
) ::
  Hunter.Status.t() | no_return()
```

Edit a status

## Parameters

  * `conn` - connection credentials
  * `id` - status identifier
  * `status` - the new text of the status
  * `options` - option list

## Options

  * `spoiler_text` - text to be shown as a warning before the actual content
  * `sensitive` - whether the media of the status is NSFW
  * `language` - ISO 639-1 language code for the status
  * `media_ids` - list of media IDs to attach to the status
  * `poll` - map with `options` (list of choices) and `expires_in`
    (seconds); replaces the current poll

# `endorse`

```elixir
@spec endorse(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.Relationship.t()
```

Feature an account on your profile

## Parameters

  * `conn` - connection credentials
  * `id` - account identifier

# `endorsements`

```elixir
@spec endorsements(Hunter.Client.t(), Keyword.t()) :: [Hunter.Account.t()]
```

Retrieve the accounts you are featuring on your profile

## Parameters

  * `conn` - connection credentials
  * `options` - option list

## Options

  * `max_id` - get a list of endorsements with id less than or equal this value
  * `since_id` - get a list of endorsements with id greater than this value
  * `limit` - maximum number of endorsements to get

# `familiar_followers`

```elixir
@spec familiar_followers(Hunter.Client.t(), [String.t() | non_neg_integer()]) :: [
  Hunter.FamiliarFollowers.t()
]
```

Find out which of the accounts you follow also follow the given accounts

## Parameters

  * `conn` - connection credentials
  * `ids` - list of account identifiers

# `favourite`

```elixir
@spec favourite(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.Status.t()
```

Favorite a status

## Parameters

  * `conn` - connection credentials
  * `id` - status identifier

# `favourited_by`

```elixir
@spec favourited_by(Hunter.Client.t(), String.t() | non_neg_integer(), Keyword.t()) ::
  [
    Hunter.Account.t()
  ]
```

Fetch the list of users who favourited the status

## Parameters

  * `conn` - connection credentials
  * `id` - status identifier
  * `options` - option list

## Options

  * `max_id` - get a list of *favourited by* ids less than or equal this value
  * `since_id` - get a list of *favourited by* ids greater than this value
  * `limit` - maximum number of *favourited by* to get, default: 40, max: 80

# `favourites`

```elixir
@spec favourites(Hunter.Client.t(), Keyword.t()) :: [Hunter.Status.t()]
```

Fetch a user's favourites

## Parameters

  * `conn` - connection credentials
  * `options` - option list

## Options

  * `max_id` - get a list of favourites with id less than or equal this value
  * `since_id` - get a list of favourites with id greater than this value
  * `limit` - maximum of favourites to get, default: 20, max: 40

# `filter`

```elixir
@spec filter(Hunter.Client.t(), String.t() | non_neg_integer()) :: Hunter.Filter.t()
```

Retrieve a filter

## Parameters

  * `conn` - connection credentials
  * `id` - filter identifier

# `filter_keyword`

```elixir
@spec filter_keyword(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.FilterKeyword.t()
```

Retrieve a filter keyword

## Parameters

  * `conn` - connection credentials
  * `id` - filter keyword identifier

# `filter_keywords`

```elixir
@spec filter_keywords(Hunter.Client.t(), String.t() | non_neg_integer()) :: [
  Hunter.FilterKeyword.t()
]
```

Retrieve the keywords grouped under a filter

## Parameters

  * `conn` - connection credentials
  * `filter_id` - filter identifier

# `filter_status`

```elixir
@spec filter_status(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.FilterStatus.t()
```

Retrieve a status filter

## Parameters

  * `conn` - connection credentials
  * `id` - status filter identifier

# `filter_statuses`

```elixir
@spec filter_statuses(Hunter.Client.t(), String.t() | non_neg_integer()) :: [
  Hunter.FilterStatus.t()
]
```

Retrieve the status filters grouped under a filter

## Parameters

  * `conn` - connection credentials
  * `filter_id` - filter identifier

# `filters`

```elixir
@spec filters(Hunter.Client.t()) :: [Hunter.Filter.t()]
```

Retrieve all filters the user owns

## Parameters

  * `conn` - connection credentials

# `follow`

```elixir
@spec follow(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.Relationship.t()
```

Follow a user

## Parameters

  * `conn` - connection credentials
  * `id` - user identifier

# `follow_requests`

```elixir
@spec follow_requests(Hunter.Client.t(), Keyword.t()) :: [Hunter.Account.t()]
```

Retrieve a list of follow requests

## Parameters

  * `conn` - connection credentials
  * `options` - option list

## Options

  * `max_id` - get a list of follow requests with id less than or equal this value
  * `since_id` - get a list of follow requests with id greater than this value
  * `limit` - maximum number of requests to get, default: 40, max: 80

# `followers`

```elixir
@spec followers(Hunter.Client.t(), String.t() | non_neg_integer(), Keyword.t()) :: [
  Hunter.Account.t()
]
```

Get a list of followers

## Parameters

  * `conn` - connection credentials
  * `id` - account identifier
  * `options` - options list

## Options

  * `max_id` - get a list of followers with id less than or equal this value
  * `since_id` - get a list of followers with id greater than this value
  * `limit` - maximum number of followers to get, default: 40, maximum: 80

**Note:** `max_id` and `since_id` for next and previous pages are provided in
the `Link` header. It is **not** possible to use the `id` of the returned
objects to construct your own URLs, because the results are sorted by an
internal key.

# `following`

```elixir
@spec following(Hunter.Client.t(), String.t() | non_neg_integer(), Keyword.t()) :: [
  Hunter.Account.t()
]
```

Get a list of followed accounts

## Parameters

  * `conn` - connection credentials
  * `id` - account identifier
  * `options` - options list

## Options

  * `max_id` - get a list of followings with id less than or equal this value
  * `since_id` - get a list of followings with id greater than this value
  * `limit` - maximum number of followings to get, default: 40, maximum: 80

**Note:** `max_id` and `since_id` for next and previous pages are provided in
the `Link` header. It is **not** possible to use the `id` of the returned
objects to construct your own URLs, because the results are sorted by an
internal key.

# `generate_pkce`

```elixir
@spec generate_pkce() :: %{
  code_verifier: String.t(),
  code_challenge: String.t(),
  code_challenge_method: String.t()
}
```

Generate a PKCE verifier/challenge pair (RFC 7636, S256)

Returns a map with `code_verifier`, `code_challenge` and
`code_challenge_method`. Pass the challenge params to
`authorization_url/3` and the verifier to `log_in_oauth/4`.

# `grouped_notifications`

```elixir
@spec grouped_notifications(Hunter.Client.t(), Keyword.t()) ::
  Hunter.GroupedNotificationsResults.t()
```

Retrieve grouped notifications, together with the accounts and statuses
they reference

## Parameters

  * `conn` - connection credentials
  * `options` - option list

## Options

  * `max_id` - get groups with id less than or equal this value
  * `since_id` - get groups with id greater than this value
  * `limit` - maximum number of groups to get, default: 40, max: 80
  * `types` - notification types to include
  * `exclude_types` - notification types to exclude
  * `grouped_types` - which types can be grouped together

# `grouped_unread_count`

```elixir
@spec grouped_unread_count(Hunter.Client.t()) :: non_neg_integer()
```

Retrieve the number of unread notification groups, capped by the server

## Parameters

  * `conn` - connection credentials

# `hashtag_timeline`

```elixir
@spec hashtag_timeline(Hunter.Client.t(), [String.t()], Keyword.t()) :: [
  Hunter.Status.t()
]
```

Retrieve statuses from a hashtag

## Parameters

  * `conn` - connection credentials
  * `hashtag` - string list
  * `options` - option list

## Options

  * `local` - only return statuses originating from this instance
  * `max_id` - get a list of timelines with id less than or equal this value
  * `since_id` - get a list of timelines with id greater than this value
  * `limit` - maximum number of statuses on the requested timeline to get, default: 20, max: 40

# `home_timeline`

```elixir
@spec home_timeline(Hunter.Client.t(), Keyword.t()) :: [Hunter.Status.t()]
```

Retrieve statuses from the home timeline

## Parameters

  * `conn` - connection credentials
  * `options` - option list

## Options

  * `max_id` - get a list of timelines with id less than or equal this value
  * `since_id` - get a list of timelines with id greater than this value
  * `limit` - maximum number of statuses on the requested timeline to get, default: 20, max: 40

# `instance_info`

```elixir
@spec instance_info(Hunter.Client.t()) :: Hunter.Instance.t()
```

Retrieve instance information

## Parameters

  * `conn` - connection credentials

## Examples

    iex> conn = Hunter.new([base_url: "https://social.lou.lt", access_token: "123456"])
    %Hunter.Client{base_url: "https://social.lou.lt", access_token: "123456"}
    iex> Hunter.instance_info(conn)
    %Hunter.Instance{description: "Mostly French  instance - <a href=\"/about/more#rules\">Read full description</a> for rules.",
              domain: "social.lou.lt", title: "Loultstodon", version: "4.3.8"}

# `list`

```elixir
@spec list(Hunter.Client.t(), String.t() | non_neg_integer()) :: Hunter.List.t()
```

Retrieve a list

## Parameters

  * `conn` - connection credentials
  * `id` - list identifier

# `list_accounts`

```elixir
@spec list_accounts(Hunter.Client.t(), String.t() | non_neg_integer(), Keyword.t()) ::
  [
    Hunter.Account.t()
  ]
```

Retrieve the accounts in a list

## Parameters

  * `conn` - connection credentials
  * `id` - list identifier
  * `options` - option list

## Options

  * `max_id` - get a list of accounts with id less than or equal this value
  * `since_id` - get a list of accounts with id greater than this value
  * `limit` - maximum number of accounts to get, default: 40; set to 0 to
    get all accounts in the list

# `list_timeline`

```elixir
@spec list_timeline(Hunter.Client.t(), String.t() | non_neg_integer(), Keyword.t()) ::
  [
    Hunter.Status.t()
  ]
```

Retrieve statuses from the given list's timeline

## Parameters

  * `conn` - connection credentials
  * `list_id` - list identifier
  * `options` - option list

## Options

  * `max_id` - get a list of timelines with id less than or equal this value
  * `since_id` - get a list of timelines with id greater than this value
  * `limit` - maximum number of statuses on the requested timeline to get, default: 20, max: 40

# `lists`

```elixir
@spec lists(Hunter.Client.t()) :: [Hunter.List.t()]
```

Retrieve all lists the user owns

## Parameters

  * `conn` - connection credentials

# `load_credentials`

```elixir
@spec load_credentials(String.t()) :: Hunter.Application.t()
```

Load persisted application's credentials

## Parameters

  * `name` - application's name

# `log_in_app`

```elixir
@spec log_in_app(Hunter.Application.t(), String.t()) :: Hunter.Client.t()
```

Retrieve an app-level access token via the client-credentials grant

The returned client can call app-scoped endpoints such as
`verify_app_credentials/1` and `register_account/2`.

## Parameters

  * `app` - application details, see: `Hunter.create_app/5` for more details.
  * `base_url` - API base url, default: `https://mastodon.social`

# `log_in_oauth`

```elixir
@spec log_in_oauth(Hunter.Application.t(), String.t(), String.t(), Keyword.t()) ::
  Hunter.Client.t()
```

Retrieve access token via the OAuth authorization-code flow

## Parameters

  * `app` - application details, see: `Hunter.create_app/5` for more details.
  * `oauth_code` - authorization code from the redirect (or the out-of-band
    form)
  * `base_url` - API base url, default: `https://mastodon.social`
  * `opts` - optional params

## Options

  * `code_verifier` - PKCE verifier matching the `code_challenge` sent to
    `authorization_url/3`, see `generate_pkce/0`
  * `redirect_uri` - must match the URI used on the authorization request;
    defaults to the app's first registered URI

# `lookup_account`

```elixir
@spec lookup_account(Hunter.Client.t(), String.t()) :: Hunter.Account.t()
```

Look up an account by its webfinger address, without requiring a search

## Parameters

  * `conn` - connection credentials
  * `acct` - the username or webfinger address (e.g. `user@domain`) to look up

# `media_attachment`

```elixir
@spec media_attachment(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.Attachment.t()
```

Retrieve a media attachment, to check the processing status of an
asynchronous upload

## Parameters

  * `conn` - connection credentials
  * `id` - attachment identifier

# `mute`

```elixir
@spec mute(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.Relationship.t()
```

Mute a user

## Parameters

  * `conn` - connection credentials
  * `id` - user identifier

# `mute_conversation`

```elixir
@spec mute_conversation(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.Status.t()
```

Mute a conversation, so its thread stops generating notifications

## Parameters

  * `conn` - connection credentials
  * `id` - status identifier

# `mutes`

```elixir
@spec mutes(Hunter.Client.t(), Keyword.t()) :: [Hunter.Account.t()]
```

Retrieve user's mutes

## Parameters

  * `conn` - connection credentials
  * `options` - option list

## Options

  * `max_id` - get a list of mutes with id less than or equal this value
  * `since_id` - get a list of mutes with id greater than this value
  * `limit` - maximum number of mutes to get, default: 40, max: 80

# `new`

```elixir
@spec new(Keyword.t()) :: Hunter.Client.t()
```

Initializes a client

## Options

  * `base_url` - URL of the instance you want to connect to
  * `access_token` - [String] OAuth access token for your authenticated user

# `notification`

```elixir
@spec notification(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.Notification.t()
```

Retrieve single notification

## Parameters

  * `conn` - connection credentials
  * `id` - notification identifier

## Examples

    Hunter.notification(conn, 17_476)
    #=> %Hunter.Notification{account: %{"acct" => "paperswelove@mstdn.io", ...}

# `notification_group`

```elixir
@spec notification_group(Hunter.Client.t(), String.t()) ::
  Hunter.GroupedNotificationsResults.t()
```

Retrieve a single notification group by its group key

## Parameters

  * `conn` - connection credentials
  * `group_key` - notification group key

# `notification_group_accounts`

```elixir
@spec notification_group_accounts(Hunter.Client.t(), String.t()) :: [
  Hunter.Account.t()
]
```

Retrieve the accounts of all notifications in a notification group

## Parameters

  * `conn` - connection credentials
  * `group_key` - notification group key

# `notification_policy`

```elixir
@spec notification_policy(Hunter.Client.t()) :: Hunter.NotificationPolicy.t()
```

Retrieve the notification filtering policy for the user

## Parameters

  * `conn` - connection credentials

# `notification_request`

```elixir
@spec notification_request(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.NotificationRequest.t()
```

Retrieve a single notification request

## Parameters

  * `conn` - connection credentials
  * `id` - notification request identifier

# `notification_requests`

```elixir
@spec notification_requests(Hunter.Client.t(), Keyword.t()) :: [
  Hunter.NotificationRequest.t()
]
```

Retrieve notification requests (groups of filtered notifications)

## Parameters

  * `conn` - connection credentials
  * `options` - option list

## Options

  * `max_id` - get requests with id less than or equal this value
  * `since_id` - get requests with id greater than this value
  * `limit` - maximum number of requests to get, default: 40, max: 80

# `notification_requests_merged?`

```elixir
@spec notification_requests_merged?(Hunter.Client.t()) :: boolean()
```

Check whether accepted notification requests have been merged

## Parameters

  * `conn` - connection credentials

# `notifications`

```elixir
@spec notifications(Hunter.Client.t(), Keyword.t()) :: [Hunter.Notification.t()]
```

Retrieve user's notifications

## Parameters

  * `conn` - connection credentials
  * `options` - option list

## Options

  * `max_id` - get a list of notifications with id less than or equal this value
  * `since_id` - get a list of notifications with id greater than this value
  * `limit` - maximum number of notifications to get, default: 15, max: 30

## Examples

    Hunter.notifications(conn)
    #=> [%Hunter.Notification{account: %{"acct" => "paperswelove@mstdn.io", ...}]

# `oauth_server_metadata`

```elixir
@spec oauth_server_metadata(String.t()) :: map()
```

Fetch the instance's OAuth server metadata (RFC 8414)

Use this to discover supported scopes, grant types and endpoints instead
of hardcoding them. Available since Mastodon 4.3. Does not require
authentication.

## Parameters

  * `base_url` - API base url, default: `https://mastodon.social`

Returns the decoded metadata map (`"issuer"`, `"authorization_endpoint"`,
`"token_endpoint"`, `"scopes_supported"`,
`"code_challenge_methods_supported"`, ...).

# `pin`

```elixir
@spec pin(Hunter.Client.t(), String.t() | non_neg_integer()) :: Hunter.Status.t()
```

Pin a status to the top of the user's profile

## Parameters

  * `conn` - connection credentials
  * `id` - status identifier

# `poll`

```elixir
@spec poll(Hunter.Client.t(), String.t() | non_neg_integer()) :: Hunter.Poll.t()
```

Retrieve a poll

## Parameters

  * `conn` - connection credentials
  * `id` - poll identifier

# `public_timeline`

```elixir
@spec public_timeline(Hunter.Client.t(), Keyword.t()) :: [Hunter.Status.t()]
```

Retrieve statuses from the public timeline

## Parameters

  * `conn` - connection credentials
  * `options` - option list

## Options

  * `local` - only return statuses originating from this instance
  * `max_id` - get a list of timelines with id less than or equal this value
  * `since_id` - get a list of timelines with id greater than this value
  * `limit` - maximum number of statuses on the requested timeline to get, default: 20, max: 40

# `push_subscription`

```elixir
@spec push_subscription(Hunter.Client.t()) :: Hunter.WebPushSubscription.t()
```

Retrieve the Web Push subscription tied to the access token

## Parameters

  * `conn` - connection credentials

# `reblog`

```elixir
@spec reblog(Hunter.Client.t(), String.t() | non_neg_integer()) :: Hunter.Status.t()
```

Reblog a status

## Parameters

  * `conn` - connection credentials
  * `id` - status identifier

# `reblogged_by`

```elixir
@spec reblogged_by(Hunter.Client.t(), String.t() | non_neg_integer(), Keyword.t()) ::
  [
    Hunter.Account.t()
  ]
```

Fetch the list of users who reblogged the status.

## Parameters

  * `conn` - connection credentials
  * `id` - status identifier
  * `options` - option list

## Options

  * `max_id` - get a list of *reblogged by* ids less than or equal this value
  * `since_id` - get a list of *reblogged by* ids greater than this value
  * `limit` - maximum number of *reblogged by* to get, default: 40, max: 80

# `register_account`

```elixir
@spec register_account(Hunter.Client.t(), map()) :: Hunter.Client.t()
```

Register a new account and obtain its access token

The given client must carry an *app-level* access token (from the OAuth
client-credentials flow); returns a new `Hunter.Client` holding the created
user's access token.

## Parameters

  * `conn` - connection credentials with the app-level access token
  * `params` - registration params

## Possible keys for params

  * `username` - desired username
  * `email` - the account owner's email address
  * `password` - the account password
  * `agreement` - whether the user agrees to the server rules and terms (must be `true`)
  * `locale` - the language of the confirmation email (e.g. `"en"`)
  * `reason` - (optional) why you want to join, when registrations require approval

# `reject_follow_request`

```elixir
@spec reject_follow_request(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.Relationship.t()
```

Rejects a follow request

## Parameters

  * `conn` - connection credentials
  * `id` - follow request id

# `relationships`

```elixir
@spec relationships(Hunter.Client.t(), [String.t() | non_neg_integer()]) :: [
  Hunter.Relationship.t()
]
```

Get the relationships of authenticated user towards given other users

## Parameters

  * `conn` - connection credentials
  * `id` - list of relationship IDs

# `remove_accounts_from_list`

```elixir
@spec remove_accounts_from_list(Hunter.Client.t(), String.t() | non_neg_integer(), [
  String.t() | non_neg_integer()
]) :: boolean()
```

Remove accounts from a list

## Parameters

  * `conn` - connection credentials
  * `id` - list identifier
  * `account_ids` - account identifiers to remove

# `remove_from_followers`

```elixir
@spec remove_from_followers(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.Relationship.t()
```

Remove an account from your followers

## Parameters

  * `conn` - connection credentials
  * `id` - account identifier

# `report`

```elixir
@spec report(
  Hunter.Client.t(),
  String.t() | non_neg_integer(),
  [String.t() | non_neg_integer()],
  String.t()
) :: Hunter.Report.t()
```

Report a user

## Parameters

  * `conn` - connection credentials
  * `account_id` - the ID of the account to report
  * `status_ids` - the IDs of statuses to report
  * `comment` - a comment to associate with the report

# `revoke_token`

```elixir
@spec revoke_token(Hunter.Application.t(), String.t(), String.t()) :: true
```

Revoke an access token

## Parameters

  * `app` - application details (must be the client the token was issued
    to), see: `Hunter.create_app/5`
  * `token` - the access token to revoke
  * `base_url` - API base url, default: `https://mastodon.social`

Returns `true` on success. Raises `Hunter.Error` if the token does not
belong to the given client.

# `search`

```elixir
@spec search(Hunter.Client.t(), String.t(), Keyword.t()) :: Hunter.Result.t()
```

Search for content

## Parameters

  * `conn` - connection credentials
  * `q` - the search query, if `q` is a URL Mastodon will attempt to fetch
    the provided account or status, otherwise it will do a local account
    and hashtag search
  * `options` - option list

## Options

  * `resolve` - whether to resolve non-local accounts

# `search_account`

```elixir
@spec search_account(Hunter.Client.t(), Keyword.t()) :: [Hunter.Account.t()]
```

Search for accounts

## Parameters

  * `conn` - connection credentials
  * `options` - option list

## Options

  * `q`: what to search for
  * `limit`: maximum number of matching accounts to return, default: 40

# `set_account_note`

```elixir
@spec set_account_note(Hunter.Client.t(), String.t() | non_neg_integer(), String.t()) ::
  Hunter.Relationship.t()
```

Set a private note on an account

## Parameters

  * `conn` - connection credentials
  * `id` - account identifier
  * `comment` - the note text; pass an empty string to clear the note

# `status`

```elixir
@spec status(Hunter.Client.t(), String.t() | non_neg_integer()) :: Hunter.Status.t()
```

Retrieve status

## Parameters

  * `conn` - connection credentials
  * `id` - status identifier

# `status_context`

```elixir
@spec status_context(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.Context.t()
```

Retrieve status context

## Parameters

  * `conn` - connection credentials
  * `id` - status identifier

# `status_history`

```elixir
@spec status_history(Hunter.Client.t(), String.t() | non_neg_integer()) :: [
  Hunter.StatusEdit.t()
]
```

Retrieve the edit history of a status

## Parameters

  * `conn` - connection credentials
  * `id` - status identifier

# `status_source`

```elixir
@spec status_source(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.StatusSource.t()
```

Retrieve the plain-text source of a status, for editing

## Parameters

  * `conn` - connection credentials
  * `id` - status identifier

# `statuses`

```elixir
@spec statuses(Hunter.Client.t(), String.t() | non_neg_integer(), Keyword.t()) :: [
  Hunter.Status.t()
]
```

Get a list of statuses by a user

## Parameters

  * `conn` - connection credentials -
  * `account_id` - account identifier
  * `options` - option list

## Options

  * `only_media` - only return `Hunter.Status.t` that have media attachments
  * `exclude_replies` - skip statuses that reply to other statuses
  * `max_id` - get a list of statuses with id less than or equal this value
  * `since_id` - get a list of statuses with id greater than this value
  * `limit` - maximum number of statuses to get, default: 20, max: 40

# `statuses_by_ids`

```elixir
@spec statuses_by_ids(Hunter.Client.t(), [String.t() | non_neg_integer()]) :: [
  Hunter.Status.t()
]
```

Retrieve multiple statuses by id

## Parameters

  * `conn` - connection credentials
  * `ids` - list of status identifiers

# `streaming_health?`

```elixir
@spec streaming_health?(Hunter.Client.t(), Keyword.t()) :: boolean()
```

Checks the streaming server's health endpoint (Mastodon 2.5+)

## Parameters

  * `conn` - connection credentials
  * `opts` - `url:` overrides the streaming base URL (`ws://`/`wss://`
    accepted and mapped to `http://`/`https://`)

See `Hunter.Streaming.health?/2`; streaming connections themselves are
opened with `Hunter.Streaming.connect/2`.

# `translate_status`

```elixir
@spec translate_status(Hunter.Client.t(), String.t() | non_neg_integer(), Keyword.t()) ::
  Hunter.Translation.t()
```

Translate a status into some language

## Parameters

  * `conn` - connection credentials
  * `id` - status identifier
  * `options` - option list

## Options

  * `lang` - ISO 639-1 language code the status should be translated into;
    defaults to the user's current locale

# `unblock`

```elixir
@spec unblock(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.Relationship.t()
```

Unblock a user

  * `conn` - connection credentials
  * `id` - user identifier

# `unblock_domain`

```elixir
@spec unblock_domain(Hunter.Client.t(), String.t()) :: boolean()
```

Unblock a domain

## Parameters

  * `conn` - connection credentials
  * `domain` - domain to unblock

# `unbookmark`

```elixir
@spec unbookmark(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.Status.t()
```

Remove a status from bookmarks

## Parameters

  * `conn` - connection credentials
  * `id` - status identifier

# `unendorse`

```elixir
@spec unendorse(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.Relationship.t()
```

Stop featuring an account on your profile

## Parameters

  * `conn` - connection credentials
  * `id` - account identifier

# `unfavourite`

```elixir
@spec unfavourite(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.Status.t()
```

Undo a favorite of a status

## Parameters

  * `conn` - connection credentials
  * `id` - status identifier

# `unfollow`

```elixir
@spec unfollow(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.Relationship.t()
```

Unfollow a user

## Parameters

  * `conn` - connection credentials
  * `id` - user identifier

# `unmute`

```elixir
@spec unmute(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.Relationship.t()
```

Unmute a user

## Parameters

  * `conn` - connection credentials
  * `id` - user identifier

# `unmute_conversation`

```elixir
@spec unmute_conversation(Hunter.Client.t(), String.t() | non_neg_integer()) ::
  Hunter.Status.t()
```

Unmute a conversation

## Parameters

  * `conn` - connection credentials
  * `id` - status identifier

# `unpin`

```elixir
@spec unpin(Hunter.Client.t(), String.t() | non_neg_integer()) :: Hunter.Status.t()
```

Unpin a status from the user's profile

## Parameters

  * `conn` - connection credentials
  * `id` - status identifier

# `unread_count`

```elixir
@spec unread_count(Hunter.Client.t()) :: non_neg_integer()
```

Retrieve the number of unread notifications, capped by the server

## Parameters

  * `conn` - connection credentials

# `unreblog`

```elixir
@spec unreblog(Hunter.Client.t(), String.t() | non_neg_integer()) :: Hunter.Status.t()
```

Undo a reblog of a status

## Parameters

* `conn` - connection credentials
* `id` - status identifier

# `update_credentials`

```elixir
@spec update_credentials(Hunter.Client.t(), map()) :: Hunter.Account.t()
```

Make changes to the authenticated user

## Parameters

  * `conn` - connection credentials
  * `data` - data payload

## Possible keys for payload

  * `display_name` - name to display in the user's profile
  * `note` - new biography for the user
  * `avatar` - base64 encoded image to display as the user's avatar (e.g. `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUoAAADrCAYAAAA...`)
  * `header` - base64 encoded image to display as the user's header image (e.g. `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUoAAADrCAYAAAA...`)

# `update_filter`

```elixir
@spec update_filter(Hunter.Client.t(), String.t() | non_neg_integer(), Keyword.t()) ::
  Hunter.Filter.t()
```

Update a filter

## Parameters

  * `conn` - connection credentials
  * `id` - filter identifier
  * `options` - option list

## Options

  * `title` - the new name of the filter group
  * `context` - contexts in which the filter is applied, list of:
    `home`, `notifications`, `public`, `thread`, `account`
  * `filter_action` - action to take when a status matches the filter, one
    of: `warn`, `hide`, `blur`
  * `expires_in` - seconds from now the filter should expire, `nil` to
    never expire
  * `keywords_attributes` - list of maps with `keyword`, `whole_word`,
    `id` and `_destroy` keys, keywords to add, update or remove in place

# `update_filter_keyword`

```elixir
@spec update_filter_keyword(
  Hunter.Client.t(),
  String.t() | non_neg_integer(),
  Keyword.t()
) ::
  Hunter.FilterKeyword.t()
```

Update a filter keyword

## Parameters

  * `conn` - connection credentials
  * `id` - filter keyword identifier
  * `options` - option list

## Options

  * `keyword` - the phrase to be matched against
  * `whole_word` - whether the keyword should consider word boundaries

# `update_list`

```elixir
@spec update_list(Hunter.Client.t(), String.t() | non_neg_integer(), Keyword.t()) ::
  Hunter.List.t()
```

Update a list

## Parameters

  * `conn` - connection credentials
  * `id` - list identifier
  * `options` - option list

## Options

  * `title` - the new title of the list
  * `replies_policy` - which replies should be shown in the list, one of:
    `followed`, `list`, `none`
  * `exclusive` - whether members of the list are removed from the home
    timeline

# `update_media`

```elixir
@spec update_media(Hunter.Client.t(), String.t() | non_neg_integer(), Keyword.t()) ::
  Hunter.Attachment.t()
```

Update a media attachment, before it is attached to a status

## Parameters

  * `conn` - connection credentials
  * `id` - attachment identifier
  * `options` - option list

## Options

  * `description` - plain-text description of the media for accessibility
  * `focus` - two floating points between -1.0 and 1.0, comma-delimited
  * `thumbnail` - path of a custom thumbnail image

# `update_notification_policy`

```elixir
@spec update_notification_policy(Hunter.Client.t(), Keyword.t()) ::
  Hunter.NotificationPolicy.t()
```

Update the notification filtering policy for the user

## Parameters

  * `conn` - connection credentials
  * `options` - option list

## Options

Each takes one of `accept`, `filter` or `drop`:

  * `for_not_following`
  * `for_not_followers`
  * `for_new_accounts`
  * `for_private_mentions`
  * `for_limited_accounts`

# `update_push_subscription`

```elixir
@spec update_push_subscription(Hunter.Client.t(), map()) ::
  Hunter.WebPushSubscription.t()
```

Update the `data` portion of the Web Push subscription

## Parameters

  * `conn` - connection credentials
  * `data` - map with `alerts` and/or `policy`

# `upload_media`

```elixir
@spec upload_media(Hunter.Client.t(), Path.t(), Keyword.t()) :: Hunter.Attachment.t()
```

Upload a media file

## Parameters

  * `conn` - connection credentials
  * `file` - media to be uploaded
  * `options` - option list

## Options

  * `description` - plain-text description of the media for accessibility (max 420 chars)
  * `focus` - two floating points, comma-delimited

**Note:** the v2 media endpoint processes large files asynchronously: the
returned attachment's `url` may be `nil` until the server finishes
processing (HTTP 202). The `id` can be attached to a status with
`create_status` as soon as processing completes.

# `user_agent`

```elixir
@spec user_agent() :: String.t()
```

User agent of the client

# `userinfo`

```elixir
@spec userinfo(Hunter.Client.t()) :: map()
```

Fetch OIDC-style claims about the authenticated user

Available since Mastodon 4.4; the token must carry the `profile` (or
`read`) scope.

## Parameters

  * `conn` - connection credentials

Returns the decoded claims map (`"iss"`, `"sub"`, `"name"`,
`"preferred_username"`, ...).

# `verify_app_credentials`

```elixir
@spec verify_app_credentials(Hunter.Client.t()) :: Hunter.Application.t()
```

Confirm that the app-level token works

## Parameters

  * `conn` - connection credentials holding an *app-level* access token,
    see `log_in_app/2`

Returns the `Hunter.Application` as the server sees it (never includes
`client_secret`; includes `scopes` and `redirect_uris` since Mastodon 4.3).

# `verify_credentials`

```elixir
@spec verify_credentials(Hunter.Client.t()) :: Hunter.Account.t()
```

Retrieve account of authenticated user

## Parameters

  * `conn` - connection credentials

## Examples

      iex> conn = Hunter.new([base_url: "https://social.lou.lt", access_token: "123456"])
      %Hunter.Client{base_url: "https://social.lou.lt", access_token: "123456"}
      iex> Hunter.verify_credentials(conn)
      %Hunter.Account{acct: "milmazz",
              avatar: "https://social.lou.lt/avatars/original/missing.png",
              avatar_static: "https://social.lou.lt/avatars/original/missing.png",
              created_at: "2017-04-06T17:43:55.325Z",
              display_name: "Milton Mazzarri", followers_count: 4,
              following_count: 4,
              header: "https://social.lou.lt/headers/original/missing.png",
              header_static: "https://social.lou.lt/headers/original/missing.png",
              id: "8039", locked: false, note: "", statuses_count: 3,
              url: "https://social.lou.lt/@milmazz", username: "milmazz"}

# `version`

```elixir
@spec version() :: String.t()
```

Returns Hunter version

# `vote`

```elixir
@spec vote(Hunter.Client.t(), String.t() | non_neg_integer(), [non_neg_integer()]) ::
  Hunter.Poll.t()
```

Vote on one or more options in a poll

## Parameters

  * `conn` - connection credentials
  * `id` - poll identifier
  * `choices` - list of option indices to vote for (zero-based); multiple
    choices are only allowed on multiple-choice polls

---

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