Skip to main content
When you find an API key during recon or in leaked source, validate it quickly to understand its scope before it gets rotated. Each section below gives the key pattern to recognise, the fastest validation command, and what a successful response looks like.

GitHub

Tokens appear as ghp_ (fine-grained PAT), github_pat_ (newer fine-grained), or a classic 40-character lowercase hex string. Fine-grained tokens have narrower scope; classic tokens may have broad repo and org access.
Valid response: JSON object with login, email, name, public_repos fields. Invalid token returns {"message":"Bad credentials"}.

GitLab

Personal access tokens follow the pattern glpat-xxxxxxxxxxxxxxxxxxxx. Project access tokens and group tokens share the same prefix but have narrower scope.
Valid response: JSON with id, username, email, name fields.

AWS

Access keys follow the pattern AKIA[0-9A-Z]{16} paired with a 40-character base64 secret key. AKIA prefix indicates a long-term IAM key; ASIA indicates a temporary STS key that also requires a session token.
Valid response from get-caller-identity: JSON with UserId, Account, Arn. An InvalidClientTokenId error means the key is invalid; AccessDenied means the key is valid but lacks permissions for that call.

Anthropic

API keys follow the pattern sk-ant-api03-xxxx. Validation requires making a real (minimal cost) API call since there is no free introspection endpoint.
Valid response: JSON with id, type: "message", content fields. Invalid key returns {"type":"error","error":{"type":"authentication_error","message":"invalid x-api-key"}}.

OpenAI

Keys use the pattern sk-[a-zA-Z0-9]{48} (classic) or sk-proj-xxxx (project-scoped). Project keys are narrower in scope than organisation keys.
Valid response from /v1/models: JSON with data array of model objects. Invalid key returns {"error":{"type":"invalid_request_error","code":"invalid_api_key"}}.

Google Cloud / GCP

Browser API keys match AIza[0-9A-Za-z-_]{35}. Service accounts come as a JSON file containing client_email, private_key, and project_id.
Note: API keys are often restricted to specific Google services. If one endpoint returns REQUEST_DENIED, try others (Maps, YouTube, Drive, Translate) before concluding the key is useless.

Stripe

Live keys match sk_live_[a-zA-Z0-9]{24}. Test keys match sk_test_xxxx and access only sandbox data (low value). The colon suffix on -u TOKEN: prevents curl from prompting for a password.
sk_test_ keys are low value. Only sk_live_ keys access real payment and customer data.

Airtable

Personal access tokens (post-Feb 2024) match pat[a-zA-Z0-9]{14}.[a-zA-Z0-9]{64}. Legacy API keys match key[a-zA-Z0-9]{14} and are deprecated but may still be valid.
Valid response from /v0/meta/bases: JSON with a bases array containing base IDs and names.

Slack

Token prefixes indicate type: xoxb- is a bot token, xoxp- is a user token, xoxa- is an app-level token, xoxs- is an internal workspace token. User tokens (xoxp-) generally have the broadest permissions.
Valid response from auth.test: JSON with ok: true, team, user, user_id fields.

Telegram Bot Token

Bot tokens follow the pattern [0-9]{8,10}:[a-zA-Z0-9_-]{35}. They are obtained through BotFather and grant control over the bot account.
Valid response from getMe: JSON with ok: true and a result object containing the bot username and ID.

Twilio

Account SIDs match AC[a-z0-9]{32} and are paired with a 32-character auth token. Both are required to authenticate.
Valid response: JSON with accounts array containing account SID, friendly name, and status.

SendGrid

API keys match SG.[a-zA-Z0-9_-]{22}.[a-zA-Z0-9_-]{43}. Scope determines what the key can do: some are scoped only to email send, others have full account access.
Valid response from /v3/scopes: JSON with a scopes array listing permission strings. Invalid token returns {"errors":[{"message":"The provided authorization grant is invalid"}]}.

Mailchimp

Keys match [a-zA-Z0-9]{32}-us[0-9]{1,2}. The suffix after the hyphen (e.g., us1, us21) identifies the datacenter and must be used in the API base URL.

HubSpot

Private app tokens match pat-[a-z]{2}-[a-zA-Z0-9-]{36}. Legacy hapikey tokens are a plain 36-character string. Legacy keys are being phased out but may still be active.

Cloudflare

API tokens are 40-character strings and can be scoped to specific zones or account resources. Global API Keys are paired with an email address and have full account access.
Valid response from /tokens/verify: JSON with success: true and result.status: "active".

Shodan

API keys are 32-character alphanumeric strings. Free-tier keys have very limited query credits; paid keys can search and download results at scale.
Valid response from /api-info: JSON with scan_credits, query_credits, plan, https fields.

NPM

Access tokens match npm_[a-zA-Z0-9]{36}. They may be scoped to specific packages or grant publish access to all packages under an account.
Valid response from /-/whoami: JSON {"username":"..."}.

Grafana

Service account tokens are JWTs starting with eyJ or match the glsa_xxx format. Bearer tokens authenticate against Grafana’s HTTP API.
Replace grafana-host with the actual hostname or IP of the Grafana instance.

Firebase / FCM

Firebase Cloud Messaging server keys follow no strict pattern. Validation requires sending a test push notification request; even with an invalid registration ID, a valid key returns a results array rather than a 401.
Valid response contains "results":[{"error":"InvalidRegistration"}]. An invalid key returns HTTP 401 with {"error":"Unauthorized"}.

Datadog

Datadog requires both an API key and an application key for most endpoints. API keys alone can only submit metrics; application keys are needed to query and manage the account.

Heroku

API keys are 36-character UUIDs ([a-f0-9-]{36}). They grant full access to the account including all apps, config vars (environment variables), and dynos.

Dropbox

Access tokens match sl.[a-zA-Z0-9_-]{135}. They provide access to the file storage of the linked Dropbox account.

PayPal

Client ID and secret are separate strings. Sandbox credentials hit api.sandbox.paypal.com; live credentials hit api.paypal.com. Start with sandbox to test the pair before trying live.
Valid response: JSON with access_token, token_type: "Bearer", expires_in fields.

Shopify Admin API

Access tokens (installed app) match shpat_[a-f0-9]{32}. The store name is part of the URL: you need both the token and the .myshopify.com subdomain.

Quick Reference