Changelog
Notable changes to this documentation site, latest first. The FilesHub product's own release notes live with the app at fileshub.zaions.com.
2026-10-22 — per-service plans, database backups, and the HTTP 402
- Not yet live until backend
2026.10.22.4is deployed; checkGET /api/version. - FilesHub is priced per service: each API has its own monthly price, listed at fileshub.zaions.com/pricing. A project that calls a service it has no plan for gets 402 naming the service (status codes). The owner's own projects are internal and never refused.
- Two new Management routes,
GET /backupsandGET /backups/{name}, behind the new token scopecan_read_backups(endpoints).
2026-10-22 — the OpenAPI spec now covers every API route
openapi.json1.8.0 gains 201 operations: every developer utility (converters, encoders, generators, text, network and date tools), notifications, pastes, short URLs, webhooks, mock APIs, uptime monitors, vault, push, and the newer Management routes (email batches, email-marketing reports, sequence step approve/hold,api-keys/lookup,projects/{project}/ai/lease).- Each generated operation names its server, its auth, its path parameters and its request fields from the validation rules, and carries
x-generated: true. See OpenAPI spec.
2026-10-10 — AI credit routing: which AI account and tier a project uses
- Not yet live. The backend release that carries it (
2026.10.10.1) is built and committed; checkGET /api/version. - Three new routes, described in Management API endpoints:
GET /projects/{project}/ai/routeandPOST /projects/{project}/ai/usageon the Management plane (can_read_ai_accounts), and the browser-safeGET /api/v1/ai/status. - AI accounts gain credit grants with expiry dates, reserved and shared accounts, and a balance-capped tier. The account records in
GET /ai-accountsnow carry acreditsblock. openapi.jsongains the 3 paths.
2026-09-30 — payment accounts: Stripe, PayPal, Polar.sh and 19 more
- Live since 2026-09-30 (backend
2026.09.30.3). - A new page, Payment accounts. Keys, webhook secrets and login details for 22 payment providers, entered in the dashboard. Only the account email is required.
- A new token flag,
can_read_payment_accounts(default off). No other flag grants it. openapi.jsongains the 5 read-only paths.
2026-09-29 — email marketing: lists, imports, drip sequences, one-click unsubscribe
- Not yet live. The backend release that carries it is built and committed; these endpoints behave as documented once it is deployed. Check
GET /api/version. - 🔴 A new section, Email marketing. Per-project contact lists; imports by CSV (with a column map), by pasting addresses, or one at a time — all through one pipeline whose counters always add up; project-wide suppression; RFC 8058 one-click unsubscribe; double opt-in sign-up forms; drip sequences with tracks and conditions on clicks and product events; click tracking; and product events (
signed_up,activated). API reference · product integration recipe. - A new key flag,
can_manage_email_marketing(default off), on API keys and access tokens. It is a flag, not a service permission, because the endpoints return personal data — and every one of them exceptsubscriberefuses a browserOrigin. - Email templates:
is_marketingandlayouton create. A marketing template belongs to one project, is invisible to other projects' keys, and cannot be sent throughPOST /emails/send. openapi.jsongains the 49 new paths (both planes) under theEmail marketingtag.
2026-09-16 — the vault takes a file of any format, and the OTA signing key has a home
- Not yet live. Backend
2026.09.16.1is built and committed; these endpoints behave as documented once it is deployed. - 🔴 A new freeform service,
general_files— it accepts any file, of any format, under a key you name. There is no allow-list, no extension check and no content sniffing anywhere on the upload path. Previously a file could only be stored on a key the registry declared as a file field, so anything else — a.pem, a.zip, a recovery-codes.txt— had nowhere to go. It is deliberately separate fromgeneral, which holds freeform text: the two row kinds share a(project, service, key)identity in different tables, so one service accepting both would let them shadow each other. mime_typeis documented on both upload forms. It is what "pick the file type" means: recorded, handed back on read, optional, and never validated against a list.- A new field,
native_update.signing_private_key(type: file,secret: true). The OTA platform stores a signing key's public half and fingerprint and never the private key, so a locally generated one has no second copy anywhere; this gives it one. It carries noenv_key, so no generated.envblock can ever contain it. - Two limits, neither about format: 10 MB per file (raised from 1 MB), and 100 files per project —
422 VAULT_FILE_LIMIT_REACHED. The second keeps the un-paginated file list inGET /projects/{project}/vaultfinite; replacing a file you already store is not a new file. - Two refusals now name the endpoint that would have worked instead of dead-ending: a file sent to
generalpoints atgeneral_files, and a string sent togeneral_filespoints atvault-files. - Corrected: the
GET /vault/servicesdescription inopenapi.jsonclaimed "18 services and 87 fields" andllms.txtclaimed "20 services, 95 fields". Both had been stale for months. They now tell you to count from the response, which is what the page itself has always said.
2026-09-11 — a client's project is never sent a test event or kept alive
- Live. Backend
2026.09.11.3was deployed on 2026-09-11. - 🔴 A new project flag,
is_client_project(boolean, defaultfalse). It marks a client's project and outranks both switches: such a project is never sent a "Test Analytics" event and never has its Google OAuth clients kept alive, whatevertest_events_enabledandgoogle_oauth_keepalive_enabledsay. The switches already default off; the flag is a second, independent layer, so a switch turned on by mistake still cannot reach a client's analytics, OAuth clients or database. It is written onPATCH /projects/{project}withcan_write_vault(422without it), and every project payload carries it. - A new
409 CLIENT_PROJECT, checked before the switch, on a credential-checksendand on a keep-alive run.detailsis{"is_client_project": true}. Averifyrun and the OAuth import still work on a client project, because neither sends anything. - The daily test events, the daily keep-alive and a queued run's
"all_enabled"never select a client project, and a queued run that lists one records it asskipped. A client project's OAuth clients readkeepalive.enabled: false. - 🔴 The Supabase keep-alive honours it too. A registration is never kept alive when it is flagged as a client's database itself, or when any FilesHub project linked to it is a client project.
GET /supabase-projectsgainskeepalive.client_project, that effective value, besidekeepalive.enabled. - OpenAPI spec:
is_client_projecton the project schemas and thePATCHbody,CLIENT_PROJECTon both operations, andkeepalive.enabled+keepalive.client_projecton the Supabase project schema (enabledhad been missing from it since2026.08.23.1).
2026-09-11 — OAuth client ids stored on the vault get the keep-alive
- Live. Backend
2026.09.11.2was deployed on 2026-09-11. - 🔴 A fifth import source,
vault. Client ids already stored on thegoogle_cloudvault service (oauth_web_client_id,oauth_android_client_idandoauth_ios_client_id) are registered as web, Android and iOS clients, so they are kept alive too. No Google API lists an OAuth client created by hand in Cloud Console. Recording its id ongoogle_cloudis how such a client gets the keep-alive. - 🔴 No secret is taken from Supabase any more. Supabase's auth-config API returns the Google provider's secret as a SHA-256 hash, not the secret itself.
2026.09.11.1compared that hash with the vault, which reported a falseconflictsentry, and could write it into a blankoauth_web_client_secret. The import now reads client ids only from Supabase and never stores a 64-hex value as a secret. - A sign-in provider still picks the primary web client. When Firebase Auth or Supabase Auth names a web client, that client wins;
vaultis the lowest priority. A stored value that does not end in.apps.googleusercontent.comis ignored and reported innotes. - The report's
sourcesgains avaultkey:ok (N client id(s)), orskipped: no OAuth client id stored on google_cloud. - An Android config failure now carries Google's own message, e.g.
(HTTP 400: …The length of field 'display_name' value exceeds 63 characters.), where2026.09.11.1stopped at the status code. That particular 400 is a Google-side failure; Troubleshooting explains the cause and the way round it. - OpenAPI spec:
vaultadded to a client'ssourcesenum and to the import report'ssourcesdescription.
2026-09-11 — "Test Analytics" credential checks and the Google OAuth keep-alive
- Live. Backend
2026.09.11.1, which carries both features below, was deployed on 2026-09-11. - 🔴 New page: Credential checks. Send a real "Test Analytics" event to a project's Amplitude, Sentry, Firebase Analytics and GA4 — or verify every stored analytics, error and push credential read-only — and get one verdict per tool. The page is honest about the limits. Amplitude and Sentry acknowledge what they receive, and Firebase proves its config. GA4 answers the same for any id. Clarity has no server-side event API at all.
- 🔴 New page: Google OAuth clients and keep-alive. Google deletes an OAuth client that makes no token request for six months. FilesHub now imports every client a project owns, from Firebase,
google-services.jsonand Supabase, and exercises each one daily. - 🔴 Both are opt-in per project, and off by default, so a client project is never sent a test event or has its tokens used. The two switches are writable on
PATCH /projects/{project}. - Project vault lists two new services:
google_analytics(a GA4 property Firebase did not create) andyandex_metrica.
2026-09-10 — a server's X-App-Id no longer refuses its own requests
- API key restrictions, the
allow_no_originendpoint notes and the OpenAPI spec now say what release2026.09.10.1changes. On a key with Allow No Origin, a request with noOriginis accepted whateverX-App-Idit carries. Earlier releases refused an app id the key did not list, even though the same request without the header got through, so a server that labelled itself for the audit log was locked out. - Unchanged: a request whose
Originis not allowed is still refused, with or without an app id, and a key without Allow No Origin still checksX-App-Idas a native-app identity.
2026-09-04 — a 22nd developer-account provider, and formats that both write planes enforce
- Developer accounts now lists 22 providers, adding
native_update— the account-wide token that administers every over-the-air app on a native-update account. Backend2026.09.04.1. - 🔴 New section: a provider name may also be a project-vault service. Six names appear in both places, and the page now says plainly why that is not duplication: the vault row is that project's configuration (a DSN, an extension id, an OTA app id and its device key), the developer account is the credential that administers every one of them. A DSN says where errors go; an auth token can delete the project.
- 🔴 New section: a field may declare a format. A value that does not match is refused on write with 422
INVALID_DEVELOPER_ACCOUNT_CREDENTIAL, anddetailsnames the provider and field — never the value, because an error that echoes what was sent puts a credential into the response body, your log and your CI transcript. Documented with the real error body. - The rule this closes was real: the format check ran in the admin form and not on the API, so a value the form refused could still be stored over the write plane. Two planes disagreeing is worse than neither checking.
2026-09-01 — developer accounts, debug keystores, and the two releases this site had missed
- 🔴 New page: Developer accounts. The tokens that publish under your name — npm, Hugging Face, Docker Hub, PyPI, crates.io, the extension stores, Vercel, Netlify, Sentry — on one account-level record, because a publish token authorises an account, not a project. One npm token publishes every package you own; copying it into each project's vault is not storing one credential, it is storing fifty copies and rotating means finding all fifty. Backend
2026.09.01.1. - 🔴 The reveal hands back a
.npmrcline, not a string.config_filescarries the literal dotfile content, so CI writes what it was given. A job that re-derives//registry.npmjs.org/:_authToken=gets the prefix subtly wrong once and then cannot publish — while the error blames authentication. There is noviteornextblock and there never will be: every field on a developer account authenticates a publish, so a browser bundle is exactly where none of it belongs. - 21 providers ship declared, and the page tells you not to trust that number —
GET /developer-accounts/providersreturns the live list, because adding a provider is a config entry that needs no release note. - 🔴 New page: Debug keystores — shipped in backend
2026.08.31.2and undocumented here until now. A debug keystore is generated per machine, not per app, so it is stored once and every project's vault payload carries it as a derived block. The page leads with why you care: Google Sign-In, App Links and Firebase each fail in a way that never mentions signing, and all three are a fingerprint nobody wrote down. - 🔴 No new scope for debug keystores, and the page says why. A new scope defaults to
falseon every token that already exists, so minting one 403s every caller until each is edited. That cost is worth paying for a credential and not for a fingerprint, which ships publicly inassetlinks.jsonand authorises nothing alone. Developer accounts made the opposite call, for the opposite reason. - 🔴 Authentication listed five scopes; there are eight.
can_write_vaultshipped in2026.08.20.1and appeared nowhere on that page — not in the table, not in theGET /tokensample.can_read_ai_accountsandcan_read_developer_accountswere missing too. All three are now documented, and the sample payload shows the full set. - 🔴 And a sentence on that page was wrong, not merely incomplete: "Only
can_reveal_vaultimplies another".can_write_vaultalso impliescan_read_vault— a caller populating a vault must be able to see which fields are already set. Corrected, with the three non-implications spelled out, because a scope that looks like it should imply another is exactly where a caller guesses. - OpenAPI: 44 → 54 paths. All ten developer-account and debug-keystore operations, linting at 0 errors / 2 accepted warnings — the documented baseline.
llms.txtandllms-full.txtcarry both subsystems, so an agent reading the machine-readable mirror gets the scope rules and theconfig_filescontract without loading a page.
2026-08-24 — Cloudflare Turnstile, and the Supabase release the site had missed
- 🔴 New page: Verify a Turnstile token.
POST /api/v1/turnstile/verifychecks a Cloudflare Turnstile token using the secret key stored in your project's vault, so the secret never has to reach your frontend. A static or Firebase-hosted app with no backend of its own can now use Turnstile without standing up a worker for one form. - 🔴 The page leads with the thing integrations get wrong: a failed challenge is
200, not4xx. A visitor failing a captcha is a normal outcome. Were it an error status, an integration would have to tell "FilesHub is broken" from "the visitor failed" by parsing a message — and one that skipped that step would treat an outage as a bot and reject every real person. Branch onsuccessfor the verdict, on the status code for whether the verdict means anything. The two409s stay distinct because store a secret and re-enter it are different fixes. - New vault service
turnstile, taking the registry to 22 services / 101 fields. Deliberately separate fromcloudflare: a project uses Turnstile without owning any Cloudflare account config, and merging them would makeconfigured_servicesreport an account that does not exist. - Action checking is documented — without it, a token minted on your signup form is a perfectly valid token on your login form. A mismatch returns
fileshub-action-mismatch; the prefix marks it as ours so a future Cloudflare code can never silently collide. - 🔴 Supabase projects was a release behind and is now current. It documented
keepalivewithoutenabled, and neitherendpoints.jwksnorconfig.jwt— all three shipped in backend2026.08.23.1. Added: the two-switch explanation (is_activeretires a registration,keepalive.enableddecides whether FilesHub may write to that database — a client project isactive: true, keepalive.enabled: false), the?keepalive=filter, and the JWT signing-key fields with the reasonendpoints.jwksis derived rather than stored. - 🔴 A
keepalive.last_statusthat never moves is not a broken project whenenabledisfalse— it is one deliberately left alone, and a skip writes no run row at all. That sentence is in the docs now because the payload alone reads like a failure.
2026-08-22 — one AI account for every project
- 🔴 An AI account can now serve every project, including projects created later. The owner keeps one or two provider accounts for a whole fleet, so the common case is not "assign this key to a project" but this key is the fleet's key. Set
all_projectson the account and there are no pivot rows to maintain — and no 56th project quietly created without it. - Two new routes, the account-centric direction:
GET|PUT /ai-accounts/{account}/projects. The existing pair assigns many accounts to one project; this assigns one account to many projects. Both needcan_write_vault, and neither ever returns a key. - 🔴
{"all_existing": true}andall_projectsare different features, and the docs now say so in a table. The first is a snapshot — every project that exists right now, future ones excluded. The second is a standing rule. Sending both in one body is a 422 rather than resolved by precedence: "all_existing wins" and "the explicit list wins" are equally defensible, so a caller should never have to guess which was implemented. - Each resolved entry reports
via: explicit | all_projects, which is what tells you where to undo it — anall_projectsentry is detachable from the account, never from the project. - 🔴 A note on a name collision: an access token also has an
all_projectsfield, meaning which projects you may reach. An AI account flagged for every project never widens a token's scope. - Corrected a stale box on Endpoints: it claimed no project had any configured service, a figure measured through a read path fixed in
2026.08.19.1. The honest count, probed 2026-08-19, is 7 of 55 — with a warning thatconfigured_servicesnow includes the derivedfileshubservice and so cannot be read as "someone entered data".
2026-08-21 — AI provider accounts
- An OpenAI or Anthropic key now lives on its own account record, not in each project's vault. That key authorises an account: it spends its balance and reaches every model on it, and two or three accounts serve a whole fleet — so copying it per project meant one secret in twenty rows, rotated in twenty places, agreeing in none. Same argument that put a Supabase personal access token on its account. Documented in AI provider accounts.
- 🔴 A new scope,
can_read_ai_accounts, andcan_reveal_vaultdoes NOT imply it. The most powerful grant over project credentials still answers403from every/ai-accountsendpoint, deliberately: it is given to a caller that should read one project's configuration, not to hand out billing. Assigning an account to a project is different again and needs onlycan_write_vault, because an assignment is a pointer and never returns a key.GET /tokennow reports six booleans. - 🔴 Many accounts per project, unlike the single Supabase link — an app routinely uses OpenAI for embeddings and Anthropic for chat, and a single foreign key would make that inexpressible.
- A reveal returns
env.nodecarrying the variable the provider's SDK actually reads. 🔴 There is noviteornextblock and there never will be — an AI key in a browser bundle is someone else spending the balance. - 🔴 Clearing a key is
{"clear_api_key": true}, not a blank value. A blankapi_keyis dropped so editing an unrelated field cannot wipe the credential, and it could not be "absent keeps, null clears" like the vault endpoints: Laravel'sConvertEmptyStringsToNullmiddleware rewrites""to null before a controller sees it, so the two are indistinguishable and that rule would have destroyed the key on any empty string. openaistays a declared vault service, marked superseded. A data migration lifted stored values onto account records additively — the originals were left in place, because deleting a credential is an owner decision. Removing the service would have orphaned every one of them.- OpenAPI spec extended to 1.5.0.
2026-08-20 — The project vault became writable
- 🔴 The vault now accepts writes, reversing a decision that was reaffirmed as recently as 2026-08-19. If you find a page, a note or a tool description still saying "no credential write endpoint exists or is planned", it is stale — that sentence was true until backend
2026.08.20.1. What changed is scale, not principle: around sixty projects times ninety-odd declared fields is not a workload a form can carry, and most of those values already sit in a local checkout, a git remote, or a console a CLI can read. The admin keeps its per-field help text and stays the better place to type a single value by hand. - Seven routes, documented in Writing to the vault: a partial per-service upsert, an atomic bulk write, a service clear (which requires an explicit
confirm), an orphan move, config-file store and delete, and a link-list replace. Each answers with the same payloadGET /projects/{project}/vaultreturns — so you confirm what landed without a second call and without needingcan_reveal_vault— plus achangesblock naming created, updated and deleted field names, never a value. - A new opt-in scope,
can_write_vault, off by default like the rest. It impliescan_read_vault(a writer must be able to see which fields are already set) and deliberately does not implycan_reveal_vault— a seeding agent should be able to fill a project in without being handed back every secret you already hold. Authentication and the endpoint reference now list five capability booleans. - What the write plane refuses, and why. A free-text service name is rejected on create — that is the entry-side half of the ISSUE-09 story, where a credential stored under an undeclared service name was invisible in three clean
200s for two weeks. An existing orphan stays deletable and movable, because the write side must be able to clean up whatever the read side can see;POST /projects/{project}/vault-moveexists for exactly that and validates the whole move before writing any of it. And for a registry-declared field the registry decides whether a value is secret — a caller-supplied flag counts only on the freeformgeneralservice, where it defaults to secret. - 🔴
fileshubis now a derived service. Its four fields — project slug, API base,fh_live_key and that key's origins — are computed from records FilesHub already holds, and writes to it are refused. Same reasoning that makessupabasea link rather than a copy: a stored second version of a credential the database already owns is two values that can drift with nothing to say which is right.GET /vault/servicesnow publisheswritableandderivedper service so you learn this from schema discovery instead of from a422. - Two new services in the registry:
firefox_addonsandedge_addons— Mozilla AMO (extension id, listing slug, JWT issuer and secret) and Microsoft Partner Center (product id, client id and secret, tenant token URL). The registry is now 20 services, 95 fields. - OpenAPI spec extended to 1.4.0: 2 new paths, 7 new methods on existing paths, and 9 new schemas.
VaultServicePayloadandVaultServiceDefinitiongainedderivedandwritable. Verified 0 errors, and 0 new warnings against the previous spec.
2026-08-01 — Supabase account tokens
- New page: Supabase account tokens. A Supabase personal access token (
sbp_…) belongs to an account, not a project — it drives the Supabase Management API andsupabase login --token, so one token reaches every project that account owns, including projects that do not exist yet. It now lives on its own account record, entered once for all the projects underneath it, and is read back over three new endpoints:GET /supabase-accounts,GET /supabase-accounts/{idOrEmail}andPOST /supabase-accounts/{idOrEmail}/reveal. The reveal returnsenv.cli=SUPABASE_ACCESS_TOKEN=…, sosupabase link/db push/functions deployneed no interactive login. - A new opt-in token scope,
can_read_supabase_tokens, off by default — and the part worth reading twice:can_manage_supabasedoes not grant it. The two have different blast radii, so they are different switches; a token holding onlycan_manage_supabasegets403from every account endpoint. Documented in Authentication (now four separate axes, with which of them imply each other stated explicitly), overview and the endpoint reference. - The Supabase project vault payload gained an
accountpointer — which account owns the project, whether it has a token stored, and the endpoint plus scope that would return it. It is a pointer and never a credential: no project endpoint returns a personal access token, whatever scopes the caller holds. - OpenAPI spec extended to 1.2.0: 3 new paths and 3 new schemas. Token introspection also gained
can_read_vaultandcan_reveal_vault, which the spec had been missing since they shipped — a client generated from 1.1.0 was unaware of both. llms.txtandllms-full.txtgained the account endpoints and the project vault, which had been omitted when that page shipped on 2026-07-31.
2026-07-31 — Project vault
- New page: Project vault. FilesHub now stores every third-party credential, config file and identifier a project needs — Firebase, Google Cloud, Sentry, OneSignal, Clarity, Amplitude, Cloudflare, Capacitor signing, GitHub, the three store consoles, OpenAI, SMTP, plus a freeform bucket — and reads them back over the Management API, including ready-to-paste
.envblocks for Vite, Next, Node and Laravel. Supabase is linked to the existing account-wide vault rather than duplicated. - Two new opt-in token scopes, both off by default and documented in Authentication:
can_read_vaultsees metadata and which credentials exist — presence flags, never a value — whilecan_reveal_vaultsees the values, the file bytes and the env blocks. A token missing one gets403 TOKEN_PERMISSION_DENIEDwithdetails.required_scope, not the anti-enumeration404used for resources; that distinction is now stated in the endpoint reference error table. GET /vault/servicespublishes the field registry itself — every field's label, where in that console to find it, whether it is secret, whether it may ship in a browser bundle, and its.envname. Schema discovery, so an agent never has to guess what a project can hold.- The generated
VITE_/NEXT_PUBLIC_blocks contain only fields markedclient_safe, and a field markedsecretis alwaysclient_safe: false. A server secret is structurally unable to appear in a client env block rather than merely omitted by convention. - OpenAPI spec extended to 1.1.0: 7 new paths and 8 new schemas, all using the 3.1 nullable form. The agent workflow gained a bootstrap-a-machine-from-the-vault recipe.
2026-07-30 — Global origins are readable over the Management API
- Documented two read-only endpoints —
GET /global-originsandPOST /global-origins/check— in the endpoint reference. Global origins apply to every restricted key and never appear in a key's own list, so previously there was no way to see them over the API; the docs said outright that none existed. Writes stay in the dashboard. The agent workflow now checks coverage before adding origins and adds only what comes backcovered: false, and API key restrictions records that the read API exists. - The check endpoint runs the same matcher request-time enforcement uses, because coverage is not string equality:
https://*.example.comcovers its subdomains and the bare apex, an apex rule covers no subdomain, andhttp://localhost:*covers every port. Extended the OpenAPI spec with both paths and theGlobalOriginPublic/GlobalOriginCheckResultschemas, and added the guidance tollms.txt/llms-full.txt. - Fixed 49 wrongly-typed nullable fields in the OpenAPI spec. The spec declares OpenAPI 3.1, but 49 properties used the 3.0
nullable: truekeyword. 3.1 removed that keyword, so it was being ignored — meaning the published spec asserted those 49 fields were non-nullable while the API genuinely returnsnull, and any client generated from it got the wrong types. They now use the 3.1 form,"type": ["string", "null"]. If you generated a client from this spec before today, regenerate it. No API behaviour changed; only the description of it was wrong.
2026-07-22 — Supabase project vault (Management API)
- Documented the Supabase project vault — read and reveal a registered Supabase project's full credential set (API keys, JWT secret, Postgres connection details, S3 keys) plus ready-to-paste React/Node/Laravel
.envblocks, over the Management API. Gated by the newcan_manage_supabaseaccess-token scope (off by default), which is a separate axis from the project scope. - Extended the OpenAPI spec with the
/api/public/v1/supabase-projectsendpoints (list, show, reveal) and addedcan_manage_supabaseto the token introspection; noted the scope in overview and authentication, and added a Supabase section tollms.txt/llms-full.txt.
2026-07-18 — Management API
- Documented the new Management API — a server-side control plane that manages projects, API keys, and origin restrictions with a user-level
fh_pat_access token: overview, authentication, the endpoint reference, and an AI agent workflow for auto-configuring a project's API key. - Extended the OpenAPI spec with the
/api/public/v1/*endpoints under a newBearerAuthscheme, and added a Management API section tollms.txt/llms-full.txt.
2026-07-14 — Full API docs + AI surfaces, GitHub Pages
- Moved to
fileshub-docs.zaions.comon GitHub Pages as the single host (Firebase Hosting removed). - Documented the email API: send (raw + template, multi-domain, queued), templates, and recurring schedules.
- Documented jobs (poll queued operations) and version & health.
- Added API key restrictions — ship a key in a React/mobile frontend with web-origin, Android package + signing-cert, and iOS bundle-id allowlisting.
- Added AI-agent surfaces: an OpenAPI 3.1 spec at
/openapi.jsonand a raw-Markdown mirror of every page under/raw/(index at/raw/manifest.json), with a "View raw Markdown" link on each page. - Added a summarized developer utilities index and expanded the API overview with scopes and the full endpoint map.
2026-06-23 — Initial public docs
- Launched
fileshub-docs.zaions.comas the public FilesHub documentation site (Docusaurus, hosted on Firebase Hosting + GitHub Pages). - Documented the storage object API: upload, download, list, and delete, with exact request/response shapes and the
{ "message": ... }error envelope. - Added Getting Started: Quick Start, Authentication (
X-API-Key, permissions, restrictions), and File visibility (publicvsprivate). - Added Integration Guides: Integrate from any app (JS/TS, React, PHP/Laravel) and Browser & mobile uploads.
- Added a platform services map of the 50+ utility endpoints, an FAQ, and a Privacy note.
- Added SEO/AI-discovery files:
robots.txt(AI-bot allowlist),sitemap.xml,llms.txt,llms-full.txt,humans.txt, and/.well-known/security.txt, plus JSON-LD (WebSite, Organization, SoftwareApplication).