• Authentication

    Marvel uses OAuth 2 to authorize API requests on behalf of users.

    • If you only need access to your own account, you can generate a personal access token.
    • If your app needs to access Marvel on behalf of other user's accounts you should implement the whole oauth2 flow to obtain access tokens

    Personal access tokens

    For local development and internal scripts, you can generate a personal access token and skip most of these steps.

    Head to marvelapp.com/oauth/devtoken to obtain your token. Once obtained, you can move on to authenticating requests.

    Note: Personal access tokens do not expire, so be careful with them. If one gets leaked, you can revoke a token here.

    OAuth 2

    Marvel supports OAuth 2, an industry-standard protocol for authorization, as well as the PKCE extension for secure use in native applications.

    Create your application

    Before you can obtain oauth tokens you need to register an application.

    Head to marvelapp.com/oauth/applications/ and create a new application.

    Which client type?

    Your application's client type depends upon the characteristics of your application - essentially it comes down to whether your application can keep a secret or not. This is true when the authorization handshake will run on a server under your control, but a client-side web app or native apps can all have their secrets stolen.

    If your app is a client-side webapp, a native (mobile or desktop) app, your client_type should be public.

    If your app has a backend component, and the authorization handshake will be done on the server, your client_type should be confidential.

    Which grant type?

    Grant type also depends on the specifics of your application and your client type.

    Marvel supports two different grant types, each of which requires a different implementation:

    The authorization_code flow is more complicated to implement, but allows you to refresh an access token upon expiry.

    The implicit grant type is simpler to implement, but is designed around the limitations of client-side webapps and is therefore less secure and less capable than the authorization_code grant. Specifically, tokens generated with the implicit grant can not be refreshed once they expire - instead the user must be sent through the authorization flow again.

    Apps with a confidential client type should be using the authorization_code grant type.

    For apps using a public client type such as webapps with no server component you should be using the implicit flow. If asking the user to authorize again once the token expires is unacceptable, or you're using a native app, you can use the authorization_code grant, but you will be required to implement the PKCE extension for user security.

    Implement the authorization flow

    The implementation depends upon the grant_type you're using and whether you're required to implement PKCE or not.

    If you'd prefer to see example code, refer to our Python oauth example or check out BotBot, a slackbot written in Swift.

    authorization_code flow (without PKCE)

    1: User is redirected to Marvel

    To obtain an oauth access token using the authorization_code grant, the first step (as with all flows) is to send the user to Marvel for them to authorize the access.

    The link should look like the one below, where client_id is the client id of your application, scope is a space-separated list of the scopes you are requesting, redirect_uri is a redirect uri specified in your application settings, and state is a random string (to be used later in the process.)

        scope=<space-separated scopes>

    The user will be presented with a screen allowing them to authorize or deny the access.

    Scopes Marvel API

    2: User is redirected back to your app with an auth code

    If the user denies your request, they'll be redirected back to your redirect_uri with error=access_denied in the query string.

    However if they authorise the request, they'll be redirected to your redirect_uri with state and code in the query string. At this point you should verify that the state value you receive matches the one you used earlier when redirecting the user to Marvel. If not - this is invalid and you should not continue.

    3: Exchange auth code for an access token

    Now you need to exchange your authorization code for an access token.

    This is done by making a application/x-www-form-urlencoded formatted POST request to the token endpoint, https://marvelapp.com/oauth/token/, with the following data:












    A successful response will be in the following format (where expires_in is a value in seconds):

      "access_token": "<access_token>",
      "expires_in": 36000,
      "refresh_token": "<refresh_token>",
      "scope": "<scope>",
      "token_type": "Bearer"

    The access token can now be used to authenticate requests, as described in authenticating requests

    Error Responses:

    • 401 invalid_grant: The provided authorization grant (e.g., authorization_code, implicit) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.

    Authenticating requests

    Once you've obtained an access token you have to be able to use it. To do so, simply set the Authorization header of your requests to Bearer <token>, replacing <token> with a valid access token.

    Failing to provide a valid access token or providing an access token that has expired will generate a 401 response from the main GraphQL endpoint. You should either refresh your access token or reauthenticate the end user.

    Refreshing access tokens using a refresh token

    Access tokens expire after a set period of time (7 days in our case). When they expire, they can be refreshed with the refresh_token returned from the original token response.

    Make a POST request to https://marvelapp.com/oauth/token/ with the following data:












    A new token should be created and the response will look like the following:

      "access_token": "<new_access_token>",
      "expires_in": 36000,
      "refresh_token": "<new_refresh_token>",
      "scope": "<scope>",
      "token_type": "Bearer"

    Again, expires_in is in seconds here.

    Available token scopes

    When choosing scopes you should follow the principle of least privilege; only ask for permissions that you actually need.

    • user:read - Read user data, including email addresses
    • projects:read - Read project data & project collaborators
    • projects:write - Modify projects & their collaborators
    • projects:delete - Delete user's projects
    • company:read - Read user's company & member data
    • company.projects:read - Read user's company's projects
    • company.teams:write - Create & modify your company's teams
    • teams:read - Read user's teams & team member data