Medium OAuth2 API

The Medium OAuth2 API enables third-party applications to authenticate and authorize users to act on their behalf on the Medium platform. Applications redirect users to Medium's authorization endpoint to obtain an authorization code, which is then exchanged for an access token and refresh token. The OAuth2 flow supports scoped permissions including basicProfile, publishPost, and listPublications, allowing developers to request only the level of access their application requires.

OpenAPI Specification

medium-oauth2-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: Medium OAuth2 API
  description: >-
    The Medium OAuth2 API enables third-party applications to authenticate
    and authorize users to act on their behalf on the Medium platform.
    Applications redirect users to Medium's authorization endpoint to
    obtain an authorization code, which is then exchanged for an access
    token and refresh token. The OAuth2 flow supports scoped permissions
    including basicProfile, publishPost, listPublications, and uploadImage,
    allowing developers to request only the level of access their
    application requires. Access tokens are valid for 60 days and can be
    refreshed using refresh tokens.
  version: '1.0'
  contact:
    name: Medium Support
    url: https://help.medium.com
  termsOfService: https://policy.medium.com/medium-terms-of-service-9db0094a1e0f
externalDocs:
  description: Medium API Authentication Documentation
  url: https://github.com/Medium/medium-api-docs#2-authentication
servers:
  - url: https://medium.com/m/oauth
    description: OAuth2 Authorization Server
  - url: https://api.medium.com/v1
    description: Token Exchange Endpoint
tags:
  - name: Authorization
    description: >-
      Endpoints for initiating the OAuth2 authorization flow by redirecting
      users to Medium's authorization page.
  - name: Tokens
    description: >-
      Endpoints for exchanging authorization codes for access tokens and
      refreshing expired access tokens.
paths:
  /authorize:
    get:
      operationId: authorizeUser
      summary: Authorize a user via OAuth2
      description: >-
        Redirects the user to Medium's authorization page where they can
        grant the application access to their account. The application
        specifies the desired scopes and a state parameter for CSRF
        protection. Upon successful authorization, Medium redirects the
        user back to the specified redirect URI with an authorization code
        and the state parameter.
      tags:
        - Authorization
      parameters:
        - name: client_id
          in: query
          required: true
          description: >-
            The client ID of the application as registered with Medium.
          schema:
            type: string
        - name: scope
          in: query
          required: true
          description: >-
            A comma-separated list of requested permissions. Available
            scopes are basicProfile, listPublications, publishPost, and
            uploadImage. The uploadImage scope is an extended scope that
            requires prior authorization from Medium.
          schema:
            type: string
        - name: state
          in: query
          required: true
          description: >-
            An arbitrary string used to prevent cross-site request forgery
            attacks. This value is returned unchanged in the callback.
          schema:
            type: string
        - name: response_type
          in: query
          required: true
          description: >-
            Must be set to "code" to indicate the authorization code
            grant flow.
          schema:
            type: string
            enum:
              - code
        - name: redirect_uri
          in: query
          required: true
          description: >-
            The URL where Medium will redirect the user after
            authorization. Must match one of the redirect URIs registered
            for the application.
          schema:
            type: string
            format: uri
      responses:
        '302':
          description: >-
            Redirects the user to Medium's authorization page. After the
            user grants or denies access, they are redirected to the
            specified redirect URI with the authorization code and state
            as query parameters.
  /tokens:
    post:
      operationId: exchangeAuthorizationCode
      summary: Exchange authorization code for tokens
      description: >-
        Exchanges an authorization code obtained from the authorization
        callback for an access token and a refresh token. The access token
        is valid for 60 days and is used to authenticate API requests on
        behalf of the user. The refresh token can be used to obtain a new
        access token when the current one expires.
      tags:
        - Tokens
      servers:
        - url: https://api.medium.com/v1
          description: Token Exchange Endpoint
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              required:
                - code
                - client_id
                - client_secret
                - grant_type
                - redirect_uri
              properties:
                code:
                  type: string
                  description: >-
                    The authorization code received from the authorization
                    callback redirect.
                client_id:
                  type: string
                  description: >-
                    The client ID of the application.
                client_secret:
                  type: string
                  description: >-
                    The client secret of the application.
                grant_type:
                  type: string
                  enum:
                    - authorization_code
                  description: >-
                    Must be set to "authorization_code" for the initial
                    token exchange.
                redirect_uri:
                  type: string
                  format: uri
                  description: >-
                    The same redirect URI used during the authorization
                    request.
      responses:
        '200':
          description: Successfully exchanged the authorization code for tokens.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenResponse'
        '401':
          description: >-
            The authorization code is invalid, expired, or the client
            credentials are incorrect.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /tokens/refresh:
    post:
      operationId: refreshAccessToken
      summary: Refresh an access token
      description: >-
        Exchanges a refresh token for a new access token. This endpoint
        is used when the current access token has expired. The new access
        token is valid for another 60 days. A new refresh token may also
        be returned.
      tags:
        - Tokens
      servers:
        - url: https://api.medium.com/v1
          description: Token Exchange Endpoint
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              required:
                - refresh_token
                - client_id
                - client_secret
                - grant_type
              properties:
                refresh_token:
                  type: string
                  description: >-
                    The refresh token obtained from a previous token
                    exchange.
                client_id:
                  type: string
                  description: >-
                    The client ID of the application.
                client_secret:
                  type: string
                  description: >-
                    The client secret of the application.
                grant_type:
                  type: string
                  enum:
                    - refresh_token
                  description: >-
                    Must be set to "refresh_token" for token refresh
                    requests.
      responses:
        '200':
          description: Successfully refreshed the access token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenResponse'
        '401':
          description: >-
            The refresh token is invalid, expired, or the client
            credentials are incorrect.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    TokenResponse:
      type: object
      description: >-
        The response from a successful token exchange or refresh
        containing the access token, refresh token, and metadata.
      properties:
        token_type:
          type: string
          enum:
            - Bearer
          description: >-
            The type of token issued. Always "Bearer".
        access_token:
          type: string
          description: >-
            The access token used to authenticate API requests on behalf
            of the user. Valid for 60 days.
        refresh_token:
          type: string
          description: >-
            The refresh token used to obtain a new access token when the
            current one expires.
        scope:
          type: array
          items:
            type: string
            enum:
              - basicProfile
              - listPublications
              - publishPost
              - uploadImage
          description: >-
            The list of scopes granted by the user during authorization.
        expires_at:
          type: integer
          format: int64
          description: >-
            The timestamp in milliseconds at which the access token
            expires.
    Error:
      type: object
      description: >-
        An error response from the Medium OAuth2 API containing error
        details.
      properties:
        errors:
          type: array
          items:
            type: object
            properties:
              message:
                type: string
                description: >-
                  A human-readable description of the error.
              code:
                type: integer
                description: >-
                  The numeric error code identifying the error type.