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.