API v1 (archived)
Read every app, its files, and recent news without authentication. Submit files to apps with a personal token.
Quick start
All endpoints live under https://black.wiki/api. Responses are JSON, CORS is open (Access-Control-Allow-Origin: *), and read endpoints are cached for ~60s.
# list apps
curl https://black.wiki/api/apps
# fetch a single file
curl https://black.wiki/api/apps/dubzly/data/some-file.jsonAuthentication
Only the submission endpoint requires authentication. Generate a personal token at /account/tokens (sign in first), then send it as a bearer token:
Authorization: Bearer bwk_xxxxxxxxxxxxxxxxxxxxxxxxTokens are shown once at creation — copy and store immediately. They can be revoked at any time from the same page.
Read endpoints
GET/api/apps
List all published apps with the public API enabled.
Query params: q (filter by name), limit (default 50, max 100), offset.
curl https://black.wiki/api/apps?limit=10
# response
{
"total": 12,
"limit": 10,
"offset": 0,
"apps": [
{
"slug": "dubzly",
"name": "Dubzly",
"summary": "Anime Sub to Sub Chrome Extension",
"homepage_url": "...",
"repo_url": "...",
"updated_at": "...",
"url": "https://black.wiki/api/apps/dubzly",
"page_url": "https://black.wiki/directory/apps/dubzly"
}
]
}GET/api/apps/<slug>
Single app metadata + owner + cross-links.
curl https://black.wiki/api/apps/dubzly
{
"slug": "dubzly",
"name": "Dubzly",
"summary": "...",
"description": "...",
"homepage_url": "...",
"repo_url": "...",
"owner": {
"username": "techish",
"display_name": null,
"profile_url": "https://black.wiki/u/techish"
},
"created_at": "...",
"updated_at": "...",
"files_url": "https://black.wiki/api/apps/dubzly/files",
"page_url": "https://black.wiki/directory/apps/dubzly"
}GET/api/apps/<slug>/files
Paged list of all files for an app.
Query params: q (search filename), letter (single a-z or #), sort = name | size | updated, dir = asc | desc, limit (default 100, max 500), offset.
curl 'https://black.wiki/api/apps/dubzly/files?letter=a&limit=20'
{
"app": { "slug": "dubzly" },
"total": 1,
"limit": 20,
"offset": 0,
"files": [
{
"filename": "anime-dub-preset-a-replica-...json",
"size_bytes": 814,
"content_type": "application/json",
"created_at": "...",
"updated_at": "...",
"url": "https://black.wiki/api/apps/dubzly/data/anime-dub-preset-a-replica-...json"
}
]
}GET/api/apps/<slug>/data/<filename>
The raw contents of a single uploaded JSON file. Served with Content-Type: application/json.
curl https://black.wiki/api/apps/dubzly/data/anime-dub-preset-a-replica-never-dreams-2026-05-20.json
{
"format": "anime-dub-preset",
"version": 1,
"name": "a-replica-never-dreams",
...
}GET/api/news
Recent black.wiki news posts.
curl https://black.wiki/api/news?limit=5
{
"total": N,
"limit": 5,
"offset": 0,
"posts": [
{
"slug": "...",
"title": "...",
"excerpt": "...",
"body": "...",
"published_at": "...",
"updated_at": "...",
"url": "https://black.wiki/news/<slug>"
}
]
}GET/api/homage
Verified registry ("Paying Homage") of people behind work on the platform. Featured-pinned, then verified, then alphabetical. Supports q, category, letter, limit, offset.
curl 'https://black.wiki/api/homage?limit=10&category=musicians'
{
"total": N,
"entries": [
{
"slug": "...",
"name": "...",
"summary": "...",
"category": "musicians",
"profile_image_url": "...",
"verified": true,
"member_number": 1001,
"member_since": "2026-06-01",
"featured": false,
"url": "https://black.wiki/homage/<slug>"
}
]
}GET/api/homage/<slug>
Full homage entry, including links and verification info.
curl https://black.wiki/api/homage/jane-doeGET/api/homage/categories
List of categories used to filter homage entries.
curl https://black.wiki/api/homage/categoriesJobs
Roles posted at black.wiki. Both open and filledare publicly readable; archived are admin-only.
GET/api/jobs
List jobs. Optional status=open|filled.
curl https://black.wiki/api/jobs
{
"jobs": [
{
"slug": "...",
"title": "...",
"summary": "...",
"compensation": "$250 / month",
"time_commitment": "~4 hours per week",
"location": "Remote",
"employment_type": "contract-1099",
"status": "open",
"url": "https://black.wiki/jobs/<slug>"
}
]
}GET/api/jobs/<slug>
Full job posting with description and apply details.
curl https://black.wiki/api/jobs/community-content-moderatorPolls
Daily community polls — open to anyone, no login required. Vote submissions go through a moderation pipeline (wordlist + heuristics + Claude on borderline cases); confirmed abuse auto-blocks the IP. A signed cookie is set on the first request to dedupe future votes.
GET/api/polls
Open and closed polls, most recent first.
curl https://black.wiki/api/polls?status=open
{
"polls": [
{
"slug": "...",
"question": "...",
"status": "open",
"daily_for": "2026-06-02",
"url": "https://black.wiki/polls/<slug>",
"api_url": "https://black.wiki/api/polls/<slug>"
}
]
}GET/api/polls/<slug>
Poll detail with options and aggregate results. Results are safe to show before voting (no per-voter info exposed).
curl https://black.wiki/api/polls/which-app
{
"slug": "which-app",
"question": "...",
"options": [{ "id": "...", "label": "...", "sort_order": 0 }],
"results": [{ "option_id": "...", "label": "...", "votes": 7, "pct": 0.41 }],
"total_votes": 17,
"vote_url": "https://black.wiki/api/polls/which-app/vote"
}POST/api/polls/<slug>/vote
Cast a vote. Dedup'd per browser (signed cookie + IP). Optional comment is moderated; the vote still records even if the comment is dropped.
curl -X POST https://black.wiki/api/polls/which-app/vote \
-H 'content-type: application/json' \
-d '{"option_id":"...","comment":"Optional reasoning"}'
{
"ok": true,
"duplicate": false,
"comment_status": "approved" | "pending" | "rejected" | "none"
}Black Sayings
Community-curated cultural phrases. Submissions go through the same moderation pipeline as poll comments — abusive content is auto-rejected and the IP is blocked.
GET/api/sayings
Published sayings. Supports q, category, region, limit, offset.
curl https://black.wiki/api/sayings?category=kitchen
{
"total": N,
"sayings": [
{
"slug": "...",
"text": "Shut the door and stop letting all the air outside",
"meaning": "...",
"attribution": "Grandma Pearl",
"region": "South",
"category": "kitchen",
"image_url": "...",
"url": "https://black.wiki/sayings/<slug>"
}
]
}GET/api/sayings/<slug>
Full saying detail, including meaning and attribution.
curl https://black.wiki/api/sayings/shut-the-doorGET/api/sayings/categories
List of categories used to filter sayings.
curl https://black.wiki/api/sayings/categoriesGET/api/sayings/random
One random published saying — handy for widgets / embeds.
curl https://black.wiki/api/sayings/randomPOST/api/sayings/submit
Submit a saying for admin review. Required: text. Optional: meaning, attribution, region, category, submitter_name, submitter_email. Returns {"status":"pending"|"spam"}.
curl -X POST https://black.wiki/api/sayings/submit \
-H 'content-type: application/json' \
-d '{"text":"You gon stop going in and out of this house","meaning":"...","region":"South"}'Submit a file (write)
Submitted files land in the app owner's pending queue. The owner approves or rejects from their manage page. Approved files become public at /api/apps/<slug>/data/<filename>.
POST/api/apps/<slug>/submit
Requires Authorization: Bearer bwk_.... Body must be JSON with filename (must end in .json), content (object or JSON-encoded string), and optional message. Max 1MB.
curl -X POST https://black.wiki/api/apps/dubzly/submit \
-H "Authorization: Bearer bwk_XXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{
"filename": "dub-preset-my-anime-2026.json",
"content": { "format": "anime-dub-preset", "version": 1, "name": "..." },
"message": "Generated by Dubzly"
}'
# response
{ "ok": true, "submission_id": "...", "message": "Submitted for review..." }Browser extension example
For a chrome/firefox extension that posts on behalf of the user (e.g. a “Share to community” button):
// background.js or popup.js
const TOKEN = (await chrome.storage.local.get("blackwikiToken")).blackwikiToken;
async function shareToCommunity(filename, content, message) {
const res = await fetch(
"https://black.wiki/api/apps/dubzly/submit",
{
method: "POST",
headers: {
"Authorization": `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ filename, content, message }),
},
);
const data = await res.json();
if (!data.ok) throw new Error(data.error);
return data.submission_id;
}Tell users to grab a token from https://black.wiki/account/tokens and paste it into your extension's settings.
Status codes
200— success400— bad request (missing fields, invalid filename, invalid JSON, file too large)401— missing or invalid bearer token403— the app's public API is disabled404— app or file not found500— server / database error
Notes
- Read endpoints are cached:
public, max-age=60, s-maxage=300. Fresh uploads may take up to ~5 min to appear via the edge cache. - App owners can disable the public API per-app at any time. Disabled apps return
403on all/api/apps/<slug>/*endpoints. - App owners can also close community submissions independently of the API. When closed,
POST /api/apps/<slug>/submitreturns an error and only the owner can use the web upload. - Submission size cap is 1MB. Direct uploads via the owner's manage page allow up to 10MB.