API reference
For LLMsEvery field configurable in the dashboard is configurable here — same schema, same source of truth.
X-RateLimit-* headers on every responseIntroduction
The Gitfile API reads and writes the same banner configuration the dashboard does, and serves the public banner image — everything over HTTPS. Every request and response body is JSON, except the banner endpoint, which returns the rendered image directly.
Authentication
Most endpoints accept either credential — whichever is present on the request:
- An API key —
Authorization: Bearer gtf_live_..., generated from Dashboard → API — the only place a key can ever be created. Each key carries one or more scopes (config:read,config:write) and can only ever act on its own account's configuration. - The dashboard's session cookie — what the dashboard itself uses; useful if you're scripting against your own logged-in browser session.
There is no endpoint to create, list, or revoke API keys — that's deliberate. Keys are managed exclusively from an authenticated dashboard session, never over the API itself, so a leaked key can never mint or delete other credentials. The public banner endpoint needs no auth at all.
Rate limits
Authenticated requests are limited to 60 requests/minute per API key; the public banner endpoint is limited to 300 requests/minute per client IP. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers — back off once Remaining hits zero rather than waiting for a 429.
Configuration
/api/v1/configRetrieve the current configuration
Returns the authenticated user's current banner configuration as JSON.
Auth: Session cookie, or an API key with the config:read scope
/api/v1/configcurl "https://gitfile.dev/api/v1/config" \
-H "Authorization: Bearer gtf_live_xxxxxxxxxxxx"The full banner configuration.
{
"displayName": "Ada Lovelace",
"bio": "Building things that compile on the first try (eventually).",
"showAvatar": true,
"customAvatarUrl": null,
"appearance": {
"theme": "dark",
"accentColor": "#0A84FF",
"layout": "wide-horizontal",
"typography": "system",
"style": "cards",
"radius": 20
},
"showFields": {
"repositories": true,
"followers": true,
"stars": true,
"contributionStreak": true,
"commits": false,
"pullRequests": false,
"issues": false,
"topLanguages": true,
"pinnedRepos": [
"gitfile",
"dotfiles"
],
"organization": false,
"location": false,
"proBadge": false,
"contributionGraph": false
},
"profilePage": {
"showLiveBanner": true,
"showReadme": true,
"showLanguageBreakdown": true,
"showPinnedRepos": true,
"showRecentActivity": true,
"showStatsGrid": true,
"showContributionHeatmap": true
},
"public": true,
"includePrivateRepos": false
}/api/v1/configReplace the configuration
Replaces the full configuration in one call — every field below is required, same as saving the entire dashboard form at once.
Auth: Session cookie, or an API key with the config:write scope
Request body
All fields required — this is a full replace, not a merge. Use PATCH below to change just a few fields.
displayNamestring1–80 characters. The banner's headline name.
biostringUp to 240 characters, shown under the display name.
showAvatarbooleanWhether the GitHub avatar is rendered.
customAvatarUrlstring | nullOverrides the GitHub avatar with a custom image URL, or null to use it.
appearanceobjectVisual style of the banner.
showFieldsobjectWhich stats and fields are visible on the banner.
profilePageobjectWhich sections are visible on the public /{username} profile page.
publicbooleanWhether the banner URL and the /{username} page render real data or a private placeholder.
includePrivateReposbooleanOpt-in to include private/org repos in aggregate stats. Requires a connected token with repo scope — this flag alone does nothing without one.
/api/v1/configcurl -X PUT "https://gitfile.dev/api/v1/config" \
-H "Authorization: Bearer gtf_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"theme":"dark","accentColor":"#0A84FF"}'The configuration as saved.
{
"displayName": "Ada Lovelace",
"bio": "Building things that compile on the first try (eventually).",
"showAvatar": true,
"customAvatarUrl": null,
"appearance": {
"theme": "dark",
"accentColor": "#0A84FF",
"layout": "wide-horizontal",
"typography": "system",
"style": "cards",
"radius": 20
},
"showFields": {
"repositories": true,
"followers": true,
"stars": true,
"contributionStreak": true,
"commits": false,
"pullRequests": false,
"issues": false,
"topLanguages": true,
"pinnedRepos": [
"gitfile",
"dotfiles"
],
"organization": false,
"location": false,
"proBadge": false,
"contributionGraph": false
},
"profilePage": {
"showLiveBanner": true,
"showReadme": true,
"showLanguageBreakdown": true,
"showPinnedRepos": true,
"showRecentActivity": true,
"showStatsGrid": true,
"showContributionHeatmap": true
},
"public": true,
"includePrivateRepos": false
}/api/v1/configUpdate part of the configuration
Partially updates specific fields without resending the whole object — nested objects (appearance, showFields) are shallow-merged too.
Auth: Session cookie, or an API key with the config:write scope
Request body
Every field is optional — send only what you want to change.
displayNamestring1–80 characters. The banner's headline name.
biostringUp to 240 characters, shown under the display name.
showAvatarbooleanWhether the GitHub avatar is rendered.
customAvatarUrlstring | nullOverrides the GitHub avatar with a custom image URL, or null to use it.
appearanceobjectVisual style of the banner.
showFieldsobjectWhich stats and fields are visible on the banner.
profilePageobjectWhich sections are visible on the public /{username} profile page.
publicbooleanWhether the banner URL and the /{username} page render real data or a private placeholder.
includePrivateReposbooleanOpt-in to include private/org repos in aggregate stats. Requires a connected token with repo scope — this flag alone does nothing without one.
/api/v1/configcurl -X PATCH "https://gitfile.dev/api/v1/config" \
-H "Authorization: Bearer gtf_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"showFields":{"contributionStreak":false}}'The full configuration after the patch is applied.
{
"displayName": "Ada Lovelace",
"bio": "Building things that compile on the first try (eventually).",
"showAvatar": true,
"customAvatarUrl": null,
"appearance": {
"theme": "dark",
"accentColor": "#0A84FF",
"layout": "wide-horizontal",
"typography": "system",
"style": "cards",
"radius": 20
},
"showFields": {
"repositories": true,
"followers": true,
"stars": true,
"contributionStreak": true,
"commits": false,
"pullRequests": false,
"issues": false,
"topLanguages": true,
"pinnedRepos": [
"gitfile",
"dotfiles"
],
"organization": false,
"location": false,
"proBadge": false,
"contributionGraph": false
},
"profilePage": {
"showLiveBanner": true,
"showReadme": true,
"showLanguageBreakdown": true,
"showPinnedRepos": true,
"showRecentActivity": true,
"showStatsGrid": true,
"showContributionHeatmap": true
},
"public": true,
"includePrivateRepos": false
}/api/v1/config/regenerateForce a cache refresh
Forces an immediate cache invalidation of the public banner image (bypassing the normal ~24h refresh schedule). No request body.
Auth: Session cookie, or an API key with the config:write scope
/api/v1/config/regeneratecurl -X POST "https://gitfile.dev/api/v1/config/regenerate" \
-H "Authorization: Bearer gtf_live_xxxxxxxxxxxx"Confirms the banner cache was invalidated.
{
"status": "regenerating",
"username": "octocat"
}/api/v1/accountDelete your account
Permanently deletes the signed-in account: saved configuration, linked identities, username claims, API keys and cached stats, and revokes the OAuth grants on GitHub/GitLab (best effort). The body must carry one of your linked usernames as a typed confirmation. Session-only: an API key cannot call this endpoint. Not reversible.
Auth: Session cookie only (API keys are rejected)
/api/v1/accountcurl -X DELETE "https://gitfile.dev/api/v1/account" \
-H "Content-Type: application/json" \
-b "gitfile_session=..." \
-d '{"confirm":"octocat"}'Confirms the account was deleted and the session cookie cleared.
{
"ok": true
}Banner
Errors
Every non-2xx response, from any endpoint above, shares the same JSON envelope: { error, message }, plus issues on a 400. The status badges under each endpoint's "Returns" link back here.
invalid_requestThe request body or query string failed validation — see `issues` for exactly which field and why.
{
"error": "invalid_request",
"message": "Invalid payload",
"issues": [
{ "path": ["appearance", "accentColor"], "message": "accentColor must be a 6-digit hex color" }
]
}unauthenticated / api_auth_errorNo session cookie and no Authorization header were provided, or the API key wasn't recognized (unknown, malformed, or revoked).
{
"error": "api_auth_error",
"message": "Missing or invalid Authorization: Bearer gtf_live_... header"
}api_auth_errorThe API key is valid but doesn't have the scope this endpoint requires (e.g. a `config:read`-only key calling a `config:write` route).
{
"error": "api_auth_error",
"message": "This API key does not have the \"config:write\" scope"
}api_auth_errorMore than 60 requests/minute for this API key (or 300/minute per client IP on the public banner endpoint). Every response carries `X-RateLimit-*` headers so you can back off before hitting this.
{
"error": "api_auth_error",
"message": "Rate limit exceeded (60 requests/minute)"
}internal_errorSomething went wrong on our end. Safe to retry with backoff.
{
"error": "internal_error",
"message": "Something went wrong"
}