GitHub profile
POST /api/v1/profiles with platform "github". Returns the shared profile fields plus 8 GitHub-specific fields. 1 credit for a fresh lookup; cache hits, samples and failures cost 0.
Request
POST /api/v1/profiles · authenticate with the x-api-key header.
| Parameter | Type | Required | Description |
|---|---|---|---|
platform | string | Yes | "github" |
handle | string | Yes | Username. |
mode | string | No | "live" for real data, "demo" for a free labeled sample. Default "demo". |
freshness | string | No | Oldest cached result you accept: "1h", "24h" (default), "7d", or "live" to force a refresh. |
REQUEST EXAMPLE
curl "$SIGNALSHELF_BASE_URL/api/v1/profiles" \
-H "Content-Type: application/json" \
-H "x-api-key: $SIGNALSHELF_API_KEY" \
--data '{"platform":"github","handle":"torvalds","mode":"demo","freshness":"24h"}'const response = await fetch(`${process.env.SIGNALSHELF_BASE_URL}/api/v1/profiles`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'x-api-key': process.env.SIGNALSHELF_API_KEY },
body: JSON.stringify({platform: "github", handle: "torvalds", mode: "demo", freshness: "24h"}),
});
const { data, meta } = await response.json();import os, requests
response = requests.post(
f"{os.environ['SIGNALSHELF_BASE_URL']}/api/v1/profiles",
headers={"x-api-key": os.environ["SIGNALSHELF_API_KEY"]},
json={"platform":"github","handle":"torvalds","mode":"demo","freshness":"24h"},
timeout=30,
)
data = response.json()["data"]Example response
Labeled sample fixture. Values are illustrative and do not describe a real creator.
EXAMPLE
{
"data": {
"platform": "github",
"handle": "torvalds",
"name": "Sample creator",
"bio": "Illustrative sample data for exploring SignalShelf. Not a real profile lookup.",
"followers": 128400,
"following": 842,
"posts": 326,
"verified": false,
"url": "https://github.com/torvalds",
"avatar": null,
"sample": true,
"provider": "sample-fixture",
"details": {
"type": null,
"company": null,
"email": null,
"twitter_username": null,
"public_repos": null,
"public_gists": null,
"hireable": null,
"updated_at": null
}
},
"meta": {
"event_id": "sample",
"mode": "demo",
"cache": "SAMPLE",
"credits_charged": 0,
"fetched_at": null,
"age_seconds": null,
"duration_ms": 0
}
}Profile fields
Every platform returns these fields. Fields a platform does not expose are null (or [] for links); they are never guessed.
| Field | Type | Description |
|---|---|---|
platform | string | Platform you requested. |
handle | string | Normalized handle (lowercase, no @). |
name | string | Display name. |
bio | string | Profile description, as shown publicly. |
followers | number | Follower or subscriber count. |
following | number | Accounts this profile follows. |
posts | number | Total posts, videos, pins or repositories, depending on platform. |
verified | boolean | Platform verification badge, when exposed. |
url | string | Canonical public profile URL. |
avatar | string | null | Profile picture URL (largest available). |
sample | boolean | Always false for live data; true only in sample mode. |
provider | string | Engine that produced the data. |
details | object | Platform-specific fields, listed below. |
GitHub-specific fields (details)
Returned inside data.details.
| Field | Type | Description |
|---|---|---|
details.type | string | null | User or Organization. |
details.company | string | null | Company. |
details.email | string | null | Public email, if the user set one. |
details.twitter_username | string | null | Linked X username. |
details.public_repos | string | null | Public repositories. |
details.public_gists | string | null | Public gists. |
details.hireable | string | null | Open to hire. |
details.updated_at | string | null | Last profile update (ISO 8601). |
Response metadata
| Field | Type | Description |
|---|---|---|
meta.cache | string | HIT (served from cache, 0 credits), MISS (fresh fetch) or SAMPLE. |
meta.credits_charged | number | Credits charged for this request. |
meta.fetched_at | string | When the data was fetched from the source. |
meta.age_seconds | number | Age of the data at response time. |
meta.duration_ms | number | Server processing time. |
Errors
Every failure is free: reserved credits are refunded automatically.
| Field | Type | Description |
|---|---|---|
404 PROFILE_NOT_FOUND | error | The profile does not exist publicly. |
422 PROFILE_UNAVAILABLE | error | The source did not expose even the public profile fields for this account. |
503 SOURCE_NOT_AUTHORIZED | error | Live access for this platform is disabled in production pending source authorization. No credits are charged. |
503 SOURCE_AUTH_REQUIRED | error | The source demanded a login for this request. Retry later. |
503 UPSTREAM_RATE_LIMITED | error | The source is rate limiting. Retry after the Retry-After header. |
402 INSUFFICIENT_CREDITS | error | Not enough credits for a fresh lookup. Cached and sample results stay free. |
Limitations
posts is the public repository count.
Explore the API in your workspace. Sample results and accepted cache hits cost zero credits. Open the playground →