Securing your SheetsAPI endpoints with API keys
Learn how GKit SheetsAPI's opt-in security model works: endpoints stay public until you create an API key, then a Bearer sk_ token is required. Covers key creation, rotation, and what API keys do and don't protect.
The opt-in security model
SheetsAPI turns any Google Sheet into a REST API, and it follows a simple rule for access control: your endpoints are public until you create an API key. This is deliberate. It lets you go from a fresh Sheet to a working API in seconds without wrestling with credentials, then lock things down the moment you're ready.
Concretely, a brand-new SheetsAPI endpoint accepts requests from anyone:
curl "https://sheetsapi.gkit.mreshank.com/api/spreadsheets/{userKey}/{sheetName}?limit=10"The first row of each tab defines the JSON field names, CORS is enabled, and you can read, append, update, and delete rows — all without a token. That's perfect for a prototype or a demo. It is not what you want for anything holding real data.
Turning on authentication
The switch is creating your first API key. Once a key exists for your account, every request must carry it as a Bearer token. Public access stops; unauthenticated calls are rejected.
You create keys after signing in with Google. Head to the sign-in page to connect your account, then generate a key from your dashboard. Keys are prefixed with sk_ so they're easy to spot in logs and config.
After that, attach the key to the Authorization header on every request:
curl "https://sheetsapi.gkit.mreshank.com/api/spreadsheets/{userKey}/{sheetName}" \
-H "Authorization: Bearer sk_your_key_here"The same header applies to writes. Appending a row (you can send a single object or an array of them) looks like this:
await fetch(
"https://sheetsapi.gkit.mreshank.com/api/spreadsheets/{userKey}/{sheetName}",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer sk_your_key_here",
},
body: JSON.stringify({ name: "Ada", email: "ada@example.com" }),
}
);Updates (PUT) and deletes (DELETE) against a specific 1-based row index use the identical header. For the full request reference, see the REST API docs and the authentication guide.
Rotating keys safely
Keys leak. They end up in a committed .env, a screenshot, or a CI log. Rotation is how you recover without downtime.
The pattern is straightforward:
- Create a new key from your dashboard while the old one is still active.
- Roll out the new key to your clients, serverless functions, and environment variables.
- Verify traffic is flowing under the new
sk_value. - Revoke the old key once nothing depends on it.
Because creating a key never disables existing ones, you can overlap them and avoid a hard cutover. A good habit is to rotate on a schedule and immediately whenever a key may have been exposed.
Keep keys off the client
API keys belong on a server, not in browser JavaScript or a mobile bundle you ship to users. Anything you embed in client-side code can be read by anyone who opens dev tools. If you need to reach SheetsAPI from a frontend, proxy the request through your own backend so the sk_ token never leaves your infrastructure.
What API keys do and don't protect
Be honest with yourself about the threat model.
What a key does: it gates access to your endpoints. Without a valid sk_ token, callers can't read or modify your data through SheetsAPI. That stops casual scraping and accidental public exposure.
What a key does not do:
- It is not row-level or field-level permissions. A valid key can hit every endpoint and operation your account exposes. There's no per-key read-only or per-tab scoping.
- It is not a substitute for not storing secrets in a Sheet. Treat your Sheet's contents as readable by anyone who holds a key.
- It does not encrypt your data or change who can open the underlying Google Sheet directly in Google Drive — that's still governed by Google's own sharing settings.
If a key is shared across many clients, treat the blast radius accordingly: a leak from any one of them compromises all of them.
A note on beta
SheetsAPI is currently in beta and free to use while it's in testing. The auth model described here — public by default, then Bearer sk_ once you create a key, plus Google OAuth for managing your account — is live today. Behavior may evolve as the product matures, so check the authentication docs for the current specifics before you build anything critical on top of it.
Ready to lock things down? Sign in with Google, create your first key, and your endpoints stop being public the moment you do.