OAuth Integration
Learn how to integrate Sentry OAuth to allow existing customers to connect their Sentry accounts to your platform.
Sentry's OAuth integration allows you to connect existing Sentry customers to your platform. This enables users to link their Sentry organizations with your product, providing seamless access to error monitoring and performance data.
The OAuth flow enables:
- Account linking between your platform and specific Sentry organizations
- Permission-based access with configurable API scopes
- User-controlled permissions with easy revocation
- Seamless authentication without requiring users to share credentials
Users sign into your platform and see a "Connect to Sentry" button with context about what permissions your product will have.
Clicking the button opens a Sentry login modal where users authenticate with their Sentry account.
After login, users see details about:
- Required permissions for your platform
- The specific Sentry organization being connected
- What actions your platform can perform
Once confirmed, your platform receives an authorization code that can be exchanged for API tokens.
Before implementing OAuth, Sentry must register your application. Contact our partnership team with:
- Client Name: Your platform name
- Redirect URIs: Your OAuth callback URLs
- Allowed Origins: Your domain(s)
- Home Page URL: Your platform's homepage
- Privacy Policy URL: Your privacy policy
- Terms and Conditions URL: Your terms of service
- Required Scopes: APIs your platform needs to access. See Permissions & Scopes for a list of scopes.
Direct users to Sentry's authorization endpoint:
https://sentry.io/oauth/authorize/?client_id=YOUR_CLIENT_ID&response_type=code&scope=SCOPE1%20SCOPE2
Parameters:
client_id
: Your registered client IDresponse_type
: Alwayscode
scope
: Space-separated list of required permissions
Example:
https://sentry.io/oauth/authorize/?client_id=0895306f2d310a075e82dff03cae9604c07e2c9465d4b990cc3f4c3010bb31d6&response_type=code&scope=project:read%20project:write
After user approval, Sentry redirects to your callback URL with an authorization code:
https://your-platform.com/oauth/sentry/callback?code=2767ac2e734ce35fe648a5f7b831bbb82776e384bb172fbcea42c292dc195e20
Make a POST request to exchange the authorization code for an access token:
import requests
TOKEN_URL = "https://sentry.io/oauth/token/"
token_data = {
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
"grant_type": "authorization_code",
"code": "AUTHORIZATION_CODE"
}
response = requests.post(TOKEN_URL, data=token_data)
tokens = response.json()
Response:
{
"access_token": "8923f2eb3ec0fb9b328ccba6280e48debe119f5b5220273ffa13fb659b2d014a",
"refresh_token": "74dbc60782aed64814513804e75e5efa6aaa67e3163744c083c0eb77478edb8b",
"expires_in": 2591999,
"expires_at": "2024-11-27T23:20:21.054320Z",
"token_type": "bearer",
"scope": "org:read project:read",
"user": {
"id": "2",
"name": "user 1",
"email": "user1@test.com"
}
}
Access tokens expire every 8 hours. Use the refresh token to get new tokens:
refresh_data = {
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
"grant_type": "refresh_token",
"refresh_token": "YOUR_REFRESH_TOKEN"
}
response = requests.post(TOKEN_URL, data=refresh_data)
new_tokens = response.json()
Scopes define what permissions your application has. Common scopes include:
org:read
- Read organization informationorg:write
- Modify organization settingsproject:read
- Read project dataproject:write
- Create and modify projectsmember:read
- Read organization membersmember:write
- Manage organization members
Required scopes depend on your use case and are documented in our API documentation.
Include the access token in API requests using the Authorization header:
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
}
response = requests.get(
"https://sentry.io/api/0/organizations/",
headers=headers
)
A Sentry user can belong to multiple organizations. The access token only provides access to the specific organization the user selected during the OAuth flow.
To get the connected organization:
# List organizations accessible with this token
response = requests.get(
"https://sentry.io/api/0/organizations/",
headers=headers
)
organizations = response.json()
# The response will only include the organization the user connected
If your application requests permissions the user doesn't have:
if response.status_code == 403:
# Handle insufficient permissions
# You may need to request additional scopes or handle gracefully
Handle expired tokens by refreshing:
if response.status_code == 401:
# Token expired, refresh it
new_tokens = refresh_access_token(refresh_token)
# Retry the original request with new token
Users can revoke your application's access at any time through their Sentry account settings (Settings → Account → Authorized Applications).
Monitor for 401 responses and handle gracefully:
if response.status_code == 401:
# Token may be revoked
# Prompt user to reconnect or handle appropriately
- Store tokens securely: Encrypt tokens in your database
- Use HTTPS: Always use HTTPS for OAuth flows
- Validate redirect URIs: Ensure redirect URIs match your registered URLs
- Handle token expiration: Implement automatic token refresh
- Monitor for revocations: Handle cases where users revoke access
Here's a complete example of handling the OAuth flow:
from flask import Flask, request, redirect, session
import requests
app = Flask(__name__)
app.secret_key = 'your-secret-key'
CLIENT_ID = 'your-client-id'
CLIENT_SECRET = 'your-client-secret'
REDIRECT_URI = 'https://your-platform.com/oauth/sentry/callback'
@app.route('/connect-sentry')
def connect_sentry():
auth_url = (
f"https://sentry.io/oauth/authorize/"
f"?client_id={CLIENT_ID}"
f"&response_type=code"
f"&scope=org:read%20project:read"
f"&redirect_uri={REDIRECT_URI}"
)
return redirect(auth_url)
@app.route('/oauth/sentry/callback')
def oauth_callback():
code = request.args.get('code')
# Exchange code for token
token_data = {
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
"grant_type": "authorization_code",
"code": code
}
response = requests.post("https://sentry.io/oauth/token/", data=token_data)
tokens = response.json()
# Store tokens securely
session['sentry_access_token'] = tokens['access_token']
session['sentry_refresh_token'] = tokens['refresh_token']
return "Successfully connected to Sentry!"
@app.route('/sentry-data')
def get_sentry_data():
access_token = session.get('sentry_access_token')
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
}
# Get organization data
response = requests.get(
"https://sentry.io/api/0/organizations/",
headers=headers
)
if response.status_code == 401:
# Token expired, refresh it
refresh_token = session.get('sentry_refresh_token')
new_tokens = refresh_access_token(refresh_token)
session['sentry_access_token'] = new_tokens['access_token']
# Retry request
response = requests.get(
"https://sentry.io/api/0/organizations/",
headers={"Authorization": f"Bearer {new_tokens['access_token']}"}
)
return response.json()
def refresh_access_token(refresh_token):
refresh_data = {
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
"grant_type": "refresh_token",
"refresh_token": refresh_token
}
response = requests.post("https://sentry.io/oauth/token/", data=refresh_data)
return response.json()
For questions about OAuth integration or partnership setup, contact: Email: partnership-platform@sentry.io
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").