Authenticated routes for external (Firebase) users. There is no server-side password registration route.
Base path: /wp-json/prc-api/v3/user-accounts/
Auth summary
Most routes use external_user_permissions_check, which validates Firebase identity from headers:
| Header | Purpose |
|---|---|
X-PRC-User-Id | Firebase user ID |
X-PRC-User-Token | Firebase ID token |
POST /get-user also requires JSON body nonce verified against prc-user-accounts.
Routes
| Method | Path | Purpose |
|---|---|---|
POST | /get-user | Return user data (nonce + auth headers) |
POST | /complete-profile | Persist profile fields after sign-in |
GET / POST | /saved-articles | List or save articles |
DELETE | /saved-articles/{post_id} | Remove a saved article |
GET / POST | /starred-files | List or star protected files |
DELETE | /starred-files/{attachment_id} | Remove a starred file |
GET / POST / DELETE | /listening-history | List, log, or clear listening history |
DELETE | /delete-user | Delete the external account (email required) |
POST | /protected-files/download | Grant a protected attachment URL and log it on the user |
POST | /protected-files/zip | Zip granted attachments and stream application/zip |
GET | /private-files/download-stats | Per-block download totals and month/day log (edit_post) |
POST | /protected-files/protect | Mark an attachment as DRM protected (upload_files) |
POST | /protected-files/unprotect | Clear protection (409 if a dataset still uses the file) |
Protected files
POST /protected-files/download body
-
attachment_idnumber required -
Media library attachment ID.
-
post_idnumber -
Host post that contains the Private Files block.
-
instance_idstring -
Private Files block instance UUID. When set with post_id, a successful grant increments that block’s download ledger.
No fields match this filter.
The token is verified before a file URL is returned. Frontend markup never includes the URL. Extra gates (dataset ATP) hook prc_user_accounts_can_grant_protected_file. The Private Files view calls this route with native fetch and Firebase headers only. Pass post_id and instance_id so WordPress can record totals, per-file counts, and month/day buckets on that block.
POST /protected-files/zip body
-
attachment_idsnumber required -
Media library attachment IDs. Capped at 50 unique IDs.
-
post_idnumber -
Host post that contains the Private Files block.
-
instance_idstring -
Private Files block instance UUID. When set with post_id, a successful zip increments that block once per unique listed file.
No fields match this filter.
Zip uses the same header auth as download. Every ID must pass grant_for_user() with source private-files-zip. Any denial returns JSON zip_blocked (403) with data.blocked and a server-composed message. Success is a zip stream. File URLs are never included in zip JSON errors. Pass post_id and instance_id so WordPress can record each unique listed file on that block.
Private Files download stats
GET /private-files/download-stats?post_id=&instance_id= requires edit_post on that post. The response is { total, files, log, daily } for that block instance only. files is all-time per-attachment counts. log and daily are yearly month and day maps, the same shape the dataset heatmap reads.
Starred files
POST /starred-files body
-
attachment_idnumber required -
Protected media library attachment ID. Title and mime are derived on the server.
No fields match this filter.
GET /starred-files returns the starredFiles map. Starring requires a protected attachment and does not run the download grant filter. Entries are { starredAt, title, mime } at users/{uid}/starredFiles/{id}.
Complete profile
POST /complete-profile body
-
firstNamestring required -
Given name.
-
lastNamestring required -
Family name.
-
captchaTokenstring -
Turnstile token when captcha is enabled.
-
countrystring -
Stored as profile location.
-
industrystring -
Industry field.
-
organizationstring -
Organization field.
No fields match this filter.
Handler writes Firebase RTDB profile data and updates Firebase Auth displayName.
Saved articles
POST /saved-articles body
-
postIdnumber required -
WordPress post ID.
-
postTitlestring -
Optional title snapshot.
-
postUrlurl -
Optional URL snapshot.
No fields match this filter.
Listening history
POST /listening-history accepts postId (required) plus optional postTitle, audioUrl, postUrl, duration, and playProgress.
Delete user
/wp-json/prc-api/v3/user-accounts/delete-user
X-PRC-User-Id firebase-uidX-PRC-User-Token firebase-id-tokenContent-Type application/json{
"email": "user@example.com"
}
{
"success": true
}