{{-- Copyright (c) ppy Pty Ltd . Licensed under the GNU Affero General Public License v3.0. See the LICENCE file in the repository root for full licence text. --}} @php use App\Libraries\ApidocRouteHelper; use Knuckles\Camel\Output\OutputEndpointData; $baseUrl = $GLOBALS['cfg']['app']['url']; $wikiUrl = wiki_url('Bot_account', null, false); $defaultHeaders = [ 'Accept' => 'application/json', 'Content-Type' => 'application/x-www-form-urlencoded', ]; @endphp

Authentication

Routes marked with the OAuth label require a valid OAuth2 token for access.

More information about applications you have registered and granted permissions to can be found here.

The API supports the following grant types:

Before you can use the osu!api, you will need to

  1. have registered an OAuth Application.
  2. acquire an access token by either:
    • authorizing users for your application;
    • requesting Client Credentials token.

Registering an OAuth application

Before you can get an OAuth token, you will need to register an OAuth application on your account settings page.

To register an OAuth application you will need to provide the:

Name Description
Application Name This is the name that will be visible to users of your application. The name of your application cannot be changed.
Application Callback URL The URL in your application where users will be sent after authorization.

The Application Callback URL is required when for using Authorization Codes. This may be left blank if you are only using Client Credentials Grants.

Your new OAuth application will have a Client ID and Client Secret; the Client Secret is like a password for your OAuth application, it should be kept private and do not share it with anyone else.

Authorization Code Grant

The flow to authorize users for your application is:

  1. Requesting authorization from users
  2. Users are redirected back to your site
  3. Your application accesses the API with the user's access token

Request authorization from a user

@php $description = 'To obtain an access token, you must first get an authorization code that is created when a user grants permissions to your application. To request permission from the user, they should be redirected to:'; $uri = route('oauth.authorizations.authorize', null, false); $endpoint = new OutputEndpointData([ 'metadata' => ['authenticated' => false, 'description' => $description], 'methods' => ['GET'], 'httpMethods' => ['GET'], 'uri' => $uri, 'queryParameters' => [ 'client_id' => [ 'description' => 'The Client ID you received when you [registered]('.route('account.edit').'#new-oauth-application).', 'name' => 'client_id', 'required' => true, 'type' => 'integer', 'example' => 1, ], 'redirect_uri' => [ 'description' => 'The URL in your application where users will be sent after authorization. This must match the registered Application Callback URL exactly.', 'name' => 'redirect_uri', 'example' => 'http://localhost:4000', ], 'response_type' => [ 'description' => 'This should always be `code` when requesting authorization.', 'name' => 'response_type', 'required' => true, 'example' => 'code', ], 'scope' => [ 'description' => 'A space-delimited string of [scopes](#scopes).', 'name' => 'scope', 'required' => false, 'example' => 'public identify', ], 'state' => [ 'description' => 'Data that will be returned when a temporary code is issued. It can be used to provide a token for protecting against cross-site request forgery attacks.', 'name' => 'state', 'required' => false, 'example' => 'randomval', ], ], ]); @endphp @include('docs.endpoint', [ 'endpoint' => $endpoint, 'showEndpointTitle' => false, 'showRequestTitle' => false, ])

User is redirected back to your site

@php $description = << If you are using `state` as protection against CSRF attacks, your OAuth client is responsible for validating this value. Exchange this `code` for an access token: --- ### Response Format Successful requests will be issued an access token: Name | Type | Description --------------|---------|----------------------------- token_type | string | The type of token, this should always be `Bearer`. expires_in | integer | The number of seconds the token will be valid for. access_token | string | The access token. refresh_token | string | The refresh token. EOT; $uri = route('oauth.passport.token', null, false); $endpoint = new OutputEndpointData([ 'bodyParameters' => [ 'client_id' => [ 'description' => 'The client ID of your application.', 'name' => 'client_id', 'required' => true, 'example' => 1, ], 'client_secret' => [ 'description' => 'The client secret of your application.', 'name' => 'client_secret', 'required' => true, 'example' => 'clientsecret', ], 'code' => [ 'description' => 'The code you received.', 'name' => 'code', 'required' => true, 'example' => 'receivedcode', ], 'grant_type' => [ 'description' => 'This must always be `authorization_code`', 'name' => 'grant_type', 'required' => true, 'example' => 'authorization_code', ], 'redirect_uri' => [ 'description' => 'This must be the same as the one used on authorization request.', 'name' => 'redirect_uri', 'required' => false, 'example' => 'http://localhost:4000', ], ], 'boundUri' => $uri, 'cleanQueryParameters' => [], 'fileParameters' => [], 'headers' => $defaultHeaders, 'metadata' => ['authenticated' => false, 'description' => $description], 'httpMethods' => ['POST'], 'queryParameters' => [], 'responses' => [ [ 'content' => [ 'access_token' => 'verylongstring', 'expires_in' => 86400, 'refresh_token' => 'anotherlongstring', 'token_type' => 'Bearer', ], 'status' => 200, ], ], 'showresponse' => true, 'uri' => $uri, 'urlParameters' => [], ]); @endphp @include('docs.endpoint', [ 'endpoint' => $endpoint, 'showEndpointTitle' => false, 'showRequestTitle' => false, ])

Refresh access token

@php $description = << [ 'client_id' => [ 'description' => 'The Client ID you received when you [registered]('.route('account.edit').'#new-oauth-application).', 'name' => 'client_id', 'required' => true, 'type' => 'integer', 'example' => 1, ], 'client_secret' => [ 'description' => 'The client secret of your application.', 'name' => 'client_secret', 'required' => true, 'type' => 'string', 'example' => 'clientsecret', ], 'grant_type' => [ 'description' => 'This must always be `refresh_token`.', 'name' => 'grant_type', 'required' => true, 'type' => 'string', 'example' => 'refresh_token', ], 'refresh_token' => [ 'description' => 'Value of refresh token received from previous access token request.', 'name' => 'refresh_token', 'required' => true, 'type' => 'string', 'example' => 'longstring', ], 'scope' => [ 'description' => "A space-delimited string of [scopes](#scopes). Specifying fewer scopes than existing access token is allowed but subsequent refresh tokens can't re-add removed scopes. If this isn't specified, existing access token scopes will be used.", 'name' => 'scope', 'required' => false, 'example' => 'public identify', ], ], 'boundUri' => $uri, 'cleanQueryParameters' => [], 'fileParameters' => [], 'headers' => $defaultHeaders, 'metadata' => ['authenticated' => false, 'description' => $description], 'httpMethods' => ['POST'], 'queryParameters' => [], 'responses' => [ [ 'content' => [ 'access_token' => 'verylongstring', 'expires_in' => 86400, 'refresh_token' => 'anotherlongstring', 'token_type' => 'Bearer', ], 'status' => 200, ], ], 'showresponse' => true, 'uri' => $uri, 'urlParameters' => [], ]); @endphp @include('docs.endpoint', [ 'endpoint' => $endpoint, 'showEndpointTitle' => false, 'showRequestTitle' => false, ])

Client Credentials Grant

@php $description = << [ 'client_id' => [ 'description' => 'The Client ID you received when you [registered]('.route('account.edit').'#new-oauth-application).', 'name' => 'client_id', 'required' => true, 'type' => 'integer', 'example' => 1, ], 'client_secret' => [ 'description' => 'The client secret of your application.', 'name' => 'client_secret', 'required' => true, 'type' => 'string', 'example' => 'clientsecret', ], 'grant_type' => [ 'description' => 'This must always be `client_credentials`.', 'name' => 'grant_type', 'required' => true, 'type' => 'string', 'example' => 'client_credentials', ], 'scope' => [ 'description' => 'Must be `public`; other scopes have no meaningful effect.', 'name' => 'scope', 'required' => true, 'type' => 'string', 'example' => 'public', ], ], 'boundUri' => $uri, 'cleanQueryParameters' => [], 'fileParameters' => [], 'headers' => $defaultHeaders, 'metadata' => ['authenticated' => false, 'description' => $description], 'httpMethods' => ['POST'], 'queryParameters' => [], 'responses' => [ [ 'content' => [ 'access_token' => 'verylongstring', 'expires_in' => 86400, 'token_type' => 'Bearer', ], 'status' => 200, ], ], 'showresponse' => true, 'uri' => $uri, 'urlParameters' => [], ]); @endphp @include('docs.endpoint', [ 'endpoint' => $endpoint, 'showEndpointTitle' => false, 'showRequestTitle' => false, ])

Using the access token to access the API

With the access token, you can make requests to osu!api on behalf of a user.

The token should be included in the header of requests to the API.

Authorization: Bearer @{{token}}

# With shell, you can just pass the correct header with each request
curl "{{ $GLOBALS['cfg']['app']['url'] }}/api/[version]/[endpoint]"
  -H "Authorization: Bearer @{{token}}"
// This javascript example uses fetch()
fetch("{{ $GLOBALS['cfg']['app']['url'] }}/api/[version]/[endpoint]", {
    headers: {
      Authorization: 'Bearer @{{token}}'
    }
});

Make sure to replace @{{token}} with your OAuth2 token.

Resource Owner

The Resource Owner is the user that a token acts on behalf of.

For Authorization Code Grant tokens, the Resource Owner is the user authorizing the token.

Client Credentials Grant tokens do not have a Resource Owner (i.e. is a guest user), unless they have been granted the {{ ApidocRouteHelper::scopeBadge('delegate') }} scope. The Resource Owner of tokens with the {{ ApidocRouteHelper::scopeBadge('delegate') }} scope is the owner of the OAuth Application that was granted the token.

Routes marked with requires user require the use of tokens that have a Resource Owner.

Client Credentials Delegation

Client Credentials Grant tokens may be allowed to act on behalf of the owner of the OAuth client (delegation) by requesting the {{ ApidocRouteHelper::scopeBadge('delegate') }} scope, in addition to other scopes supporting delegation. When using delegation, scopes that support delegation cannot be used together with scopes that do not support delegation. Delegation is only available to Chat Bots.

The following scopes currently support delegation:

Name
{{ ApidocRouteHelper::scopeBadge('chat.write') }}

Scopes

The following scopes are currently supported:

@php $scopeDescriptions = [ 'chat.read' => "Allows read chat messages on a user's behalf.", 'chat.write' => "Allows sending chat messages on a user's behalf.", 'chat.write_manage' => "Allows joining and leaving chat channels on a user's behalf.", 'delegate' => "Allows acting as the owner of a client; only available for [Client Credentials Grant](#client-credentials-grant).", 'forum.write' => "Allows creating and editing forum posts on a user's behalf.", 'friends.read' => 'Allows reading of the user\'s friend list.', 'identify' => 'Allows reading of the public profile of the user (`/me`).', 'public' => 'Allows reading of publicly available data on behalf of the user.', ]; @endphp @foreach ($scopeDescriptions as $scope => $description) @endforeach
Name Description
{{ $scope }} {!! markdown_plain($description) !!}

identify is the default scope for the Authorization Code Grant and always implicitly provided. The Client Credentials Grant does not currently have any default scopes.

Routes marked with lazer are intended for use by the osu!lazer client and not currently available for use with Authorization Code or Client Credentials grants.

Using the {{ ApidocRouteHelper::scopeBadge('chat.write') }} scope requires either

  • a Chat Bot account to send messages on behalf of other users.
  • Authorization code grant where the user is the same as the client's owner (send as yourself).

Managing OAuth applications

Your account settings page will show your registered OAuth applications, and all the OAuth applications you have granted permissions to.

Reset Client Secret

You can generate a new Client Secret by choosing to "Reset client secret", however, this will disable all access tokens issued for the application.