If you've ever tried to get your Sentry issues into a spreadsheet, you've probably hit this wall:
- The CSV export button lives in Discover, which is a Business-plan feature (~$80/mo). On the Team plan, the export link just 404s (getsentry/sentry#101587).
- Even on Business, there's no way to schedule it — the feature request for automated CSV exports (getsentry/sentry#86563) was closed as not-planned in October 2025.
The good news: Sentry's REST API is available on every plan, including the free Developer
plan — with self-serve auth tokens. And Sentry's terms of service (§4.7) expressly permit
exporting your own data through the documented API. So "export Sentry issues on the free plan"
isn't a workaround; it's a supported path that's just missing a UI.
In this tutorial we'll wire it up with Google Apps Script — zero infrastructure, runs on
Google's servers, refreshes your sheet on a schedule. Total time: ~10 minutes.
One more reason to bother: free and Team plans keep roughly 30 days of lookback. A scheduled
pull into Sheets means your issue history quietly outlives Sentry's retention window.
Why Sentry CSV export doesn't work on the free plan (and what does)
Quick map of the options:
| Method | Plan needed | Scheduled? | Cost |
|---|---|---|---|
| Discover "Export All" (UI) | Business | No | ~$80/mo |
sentry2csv CLI |
Any | DIY (cron) | Free; last release Feb 2022 |
| n8n / Coupler.io connectors | Any | Yes | Coupler.io is ~$32/mo |
| REST API + Apps Script (this post) | Any, incl. free | Yes | Free |
We'll use three documented, ungated API endpoints:
-
GET /api/0/projects/{org}/{project}/issues/— the issues list (same search syntax as the UI) -
GET /api/0/organizations/{org}/releases/— releases -
GET /api/0/organizations/{org}/stats_v2/— event volume stats
Step 1 — Create a Sentry auth token
In Sentry: Settings → Account → API → Auth Tokens → Create New Token.
Scopes you need: event:read (for the issues endpoint), project:releases (releases), and
org:read (stats). Nothing else — least privilege is your friend — this token can only read.
Copy the token somewhere safe for the next step. (Treat it like a password.)
Step 2 — Add the Apps Script to a Google Sheet
Create a new Google Sheet, then Extensions → Apps Script. Delete the placeholder code and
paste this:
// Sentry → Google Sheets, free-plan friendly.
// Endpoints used are available on ALL Sentry plans, including free Developer.
const SENTRY_API = 'https://sentry.io/api/0';
const ORG = 'your-org-slug'; // sentry.io/organizations/<this>/
const PROJECT = 'your-project-slug';
const QUERY = 'is:unresolved'; // same syntax as the Sentry search bar
const STATS_PERIOD = '14d';
function syncSentryIssues() {
const token = PropertiesService.getScriptProperties().getProperty('SENTRY_TOKEN');
if (!token) throw new Error('Set SENTRY_TOKEN in Project Settings > Script Properties first.');
const url = SENTRY_API + '/projects/' + ORG + '/' + PROJECT + '/issues/' +
'?query=' + encodeURIComponent(QUERY) +
'&statsPeriod=' + STATS_PERIOD + '&limit=100';
const resp = UrlFetchApp.fetch(url, {
headers: { Authorization: 'Bearer ' + token },
muteHttpExceptions: true,
});
if (resp.getResponseCode() !== 200) {
throw new Error('Sentry API ' + resp.getResponseCode() + ': ' + resp.getContentText());
}
const issues = JSON.parse(resp.getContentText());
const header = ['Short ID', 'Title', 'Level', 'Status', 'Events', 'Users',
'First Seen', 'Last Seen', 'Link', 'Synced At'];
const now = new Date();
const rows = issues.map(function (i) {
return [i.shortId, i.title, i.level, i.status, Number(i.count), i.userCount,
i.firstSeen, i.lastSeen, i.permalink, now];
});
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('Issues') || ss.insertSheet('Issues');
sheet.clearContents();
sheet.getRange(1, 1, 1, header.length).setValues([header]);
if (rows.length) sheet.getRange(2, 1, rows.length, header.length).setValues(rows);
}
// Run once to refresh the sheet every 6 hours automatically.
function installTrigger() {
ScriptApp.getProjectTriggers().forEach(function (t) { ScriptApp.deleteTrigger(t); });
ScriptApp.newTrigger('syncSentryIssues').timeBased().everyHours(6).create();
}
Then store your token where it doesn't live in code: Project Settings (gear icon) → Script
Properties → Add script property — name SENTRY_TOKEN, value = the token from Step 1.
Edit ORG and PROJECT to your slugs, hit Run on syncSentryIssues, approve the
authorization prompt, and check your sheet:
Step 3 — Schedule the export
Run installTrigger once. That's it — Google now refreshes the sheet every 6 hours, even with the
tab closed and your laptop off. (Adjust everyHours(6) to taste; on the free plan there's little
reason to go below 1 hour.)
More than 100 issues? The API paginates with a
Linkresponse header
(rel="next"; results="true"plus acursorparam). Loop untilresultsis"false",
appending rows as you go — left as an exercise to keep this snippet paste-able.
Bonus: releases and event stats, same trick
Both of these work with the same token, same plan, same pattern — just swap the URL:
// Your releases (version, dateCreated, commit count, ...)
SENTRY_API + '/organizations/' + ORG + '/releases/'
// Event volume by outcome (accepted / rate-limited / filtered), daily buckets
SENTRY_API + '/organizations/' + ORG + '/stats_v2/' +
'?category=error&interval=1d&statsPeriod=14d&field=sum(quantity)&groupBy=outcome'
A "Releases" tab next to your "Issues" tab gives you a poor man's release health report your PM can
actually open.
Wrap-up (and a small disclosure)
That's a free, scheduled, ToS-compliant Sentry-to-Sheets pipeline in ~50 lines. Pagination,
multiple projects, releases/stats tabs, error alerts when the token expires — all doable from here,
it's just more plumbing.
Full disclosure: I got tired of maintaining that plumbing, so I'm building IssueSheet — a
Google Sheets add-on that does all of the above in one click: Sentry issues & releases in Google
Sheets, auto-refreshed, no $80/mo Business plan needed. It's launching soon (not shipped yet —
no fake "install now" button here). If you want it, the waitlist and founding-user pre-order
($9/mo locked for life) are at: https://issuesheet.dev?utm_source=devto&utm_medium=post&utm_campaign=prelaunch
If the script above covers your needs — genuinely, just use the script. That's why it's complete.
IssueSheet is an independent tool, not affiliated with or endorsed by Sentry / Functional
Software, Inc. Sentry is a trademark of Functional Software, Inc.


