# Personal Info Hub API > Read and add to one person's collected library (links, posts, videos, transcripts) and English-practice notes. ## Quick answers: one request each Most questions take one call. Do not page through the whole library to see what is there, and do not open items one by one: filter with `since`, `source` or `q`, and add `include=content` to get each item's own text in the same answer (up to 25 items a page). Lists never carry transcripts: each item's `transcript` says whether one can be read (`state`: `ready`, `partial`, `none`, with `reason` and `message` when it is not ready) and how long it is (`chars`); open `/items/{id}/content` for the ones you need. - What did I save or watch lately, every platform: `GET https://pih-api.jiajun.fyi/items?since=7d&include=content` (`24h`, `7d`, `2w`, or a date). - Only videos I watched: `GET /items?since=7d&watched=true`. Only one platform: `GET /items?source=xiaohongshu&since=7d`. - A topic, a person's name or a pasted link: `GET /search?q=...&include=content`. Each result says where it matched (`match.field`, `match.snippet`; a transcript hit also when it is said, `match.start` / `match.end` in seconds) and whether verbatim (`match.kind: exact`), only loosely (`fuzzy`: a prefix or word stem, so `3DS` also finds `3D printing`) or by meaning (`semantic`: a transcript passage about it, so describe what was said in your own words). For a model name, code or exact phrase add `exact=true`. - An item page link (`https://jiajun.fyi/i/Ab3dE6gH/`, or an older `https://hub.jiajun.fyi/i/…` one): `GET /items/Ab3dE6gH`, the 8 characters after `/i/`; the slug is only the title's start and may be outdated. The whole link, URL-encoded, works too. - Restaurants to try or been to: `GET /restaurants` (not `/search`). - Recipes, by dish or ingredient: `GET /recipes?q=...`; ones I want to make `GET /recipes?want=true` (not `/search`). - Mark a recipe 想做: `PUT /recipes/{id}/want` with `{"want": true}`; log that I cooked it: `POST /recipes/{id}/cooked` (`{"note": ...}` optional). - Turn saved posts into recipes: `POST /recipes/import` with `{"items": [...]}`, then `GET /recipes?item=...`. - Write your own recipe version for a saved post: `POST /recipes` `{item, title, ingredients, steps}`. - Reading: `GET /books/stats?range=week`; recent highlights `GET /books/highlights`. - My todos: `GET /todos?status=open`; add one: `POST /todos` (`{"title": ...}`, with `"itemId"` when it is about a saved item: "watch this later"; set `"area": "work"` for work, life is the default, and `"project"` reusing a project name already on the list); done: `PATCH /todos/{id}` with `{"status": "done"}`. - Keep a note card (卡片笔记): `POST /card-notes` (`{"title": ..., "body": "markdown", "tags": [...]}`; reuse tags from `GET /card-notes/tags`); cards with tags: `GET /card-notes?tag=读书&tag=产品` (all of them). - Nothing new from a platform lately: `GET /connectors` tells "nothing saved" (`health: ok`) from "sync broken" (`failing`, `late`, `needs_attention`, with the error). - Tell the owner something is done: `POST /notify` (`{"title": ..., "text": ...}`). - Look something up on Xiaohongshu, Douyin, TikTok, Bilibili and others: `POST /tikhub` (`{"path": "/api/v1/...", "query": {...}}`, routes from https://api.tikhub.io/docs); it costs the owner money, so ask for what you need only. - People, things to buy, songs, English practice: `GET /people`, `GET /things/products`, `GET /songbook/songs`, `GET /english/practice`. When something fails or is missing (an error, a wrong answer, a scope or capability you need): `POST https://pih-api.jiajun.fyi/feedback` with what you tried, the error and your logs. Any key may send it. The reply's `ref` (e.g. `FB-12`) names the report; quote it when you tell the user. Personal Info Hub (PIH) is a private library: everything its owner collects from the web, X, Xiaohongshu, YouTube, Bilibili and more, with fetched text, transcripts, summaries and stored media. Authentication: send an API key as `Authorization: Bearer pih_...` (or `x-api-key: pih_...`). The owner creates keys on the hub's System page; each key carries scopes and a per-minute rate limit, and every call is logged. Rate limit headers: `x-ratelimit-limit`, `x-ratelimit-remaining`, `x-ratelimit-reset`. Scopes: `items:read` (list and read items), `media:read` (download media files by their stable address), `search:read` (search), `collect:write` (add links), `notes:write` (star items, mark or clear 稍后读 / 稍后看 (read or watch later), set an item's note), `english:read` (English-practice words and records), `songbook:read` / `songbook:write` (the 点歌本 songs and their streaming links, and 图图乐谱: each song's sheet music; write also adds songs), `things:read` / `things:write` (物品: search products, record what the owner wants to buy), `restaurants:read` / `restaurants:write` (餐厅: restaurants to try or been to, and each visit), `books:read` / `books:write` (读书: the owner's WeRead books, highlights, thoughts and reading time; write only asks for a sync now), `people:read` / `people:write` (人物: people in the library, interviewed, hosting, writing or written about, with their items), `recipes:read` / `recipes:write` (菜谱: dishes worked out from collected posts and videos, with ingredients, steps and the owner's 想做 / 做过 marks; write marks 想做, logs 做过, plans meals, adds grocery lines, turns saved posts into recipes and writes your own recipe version), `todos:read` / `todos:write` (待办: the owner's todo list; add, change, complete or drop a todo), `card_notes:read` / `card_notes:write` (卡片笔记: the owner's 卡片盒 (card box) of short tagged notes; write adds and changes cards and takes one back, nothing deletes), `tutu:read` (图图: the owner's child's photos and videos from the growth timeline, his daycare days (arrival, pick-up, naps), the family's home logs (sleep, wake-up, meals, poops, photos) and his growth measurements' numbers, read-only), `tutu:write` (图图's home logs: log a tap, add its photos, change it or take it back; nothing deletes), `health:read` / `health:write` (图图健康: his health records, vaccines, attachments and the notes on measurements; write adds measurements and adds or changes records. Sensitive: never part of every-app access, ticked by name), `notify:write` (send the owner a notification, by default to the dev bot), `tikhub:call` (make a TikHub request through the hub, on the owner's TikHub balance and budget), `renders:read` / `renders:write` (渲染: Blender renders on the home machines, queued with the rest of the owner's background work), `feedback:read` (list and resolve agent feedback; sending it needs no scope), `admin` (everything). Nothing in this API deletes data (taking back a 想做 or a planned meal only clears that mark). Media (images, video, audio) comes two ways, never as storage keys: `url`, a signed link that expires after one hour and is fetched without the key (for a tool that cannot send it); and `stableUrl` (`/items/{id}/media/{mediaId}`), which never changes and may be stored, fetched with the key and scope `media:read`. Times are ISO 8601 UTC. Ids: `id` is the item's short public id (8 characters, the same one in the hub's item URLs); an older id an item was known by still resolves. Answers: a success is the object itself, no envelope. A paged list is `{"items": [...], "nextCursor": "..."}`: send `nextCursor` back as `cursor` until it is null. Errors: `{"error": "", "message": "..."}`; branch on `error` (stable snake_case), show `message` to people. Each operation lists its codes. A malformed parameter or body names the field in `message`; a body that fails its schema also lists every issue in `details`. ## When to use this API - The user asks about something they saved, watched, bookmarked or collected: a post, an article, a video, a podcast, a recipe. - The user wants what a saved video actually says or shows, with the moment it happens. - The user wants to save a link into their library, star an item or leave a note on it. - The user wants to read or watch something later (an article or a video): that is 稍后读 / 稍后看 on the item, one mark for both, not a todo. Not for: the open web (only what the owner collected is here), deleting anything, or other people's libraries. ## Agent workflow 1. Read the key from the `PIH_API_KEY` environment variable, or from `~/.personal-info-hub/pih.env` (written by `pih login`). Never ask the user to paste it into chat or put it in browser code. Without one, run `pih login --scopes ` (or ask the user to): it prints a link the owner opens to approve, then stores the key in that file without printing it. 2. Find and read in one call: `GET https://pih-api.jiajun.fyi/search?q=...&include=content` for a topic or a pasted link; `GET https://pih-api.jiajun.fyi/items?include=content` with `since`, `source`, `starred=true` to browse; `readLater=true` is the owner's read / watch later queue (articles and videos together, `format` tells them apart), newest mark first. Each item's `content` has `body` and `readAs`; its `transcript` says whether a transcript can be read and, when not, why (`awaiting_video` and `processing` will come; `failed`, `not_captured`, `no_speech` will not). 3. Open one item only when you need more than that: `GET https://pih-api.jiajun.fyi/items/{id}/content` for the transcript as timed sentences (`transcript.segments`: `start`, `end`, `text`), signed media links and `translatedBody`, following its `readAs.route`: - `timeline`: a video or episode with real speech. Read `GET /items/{id}/timeline` (Markdown, time-stamped); that is the whole spoken content. - `body`: an article, post or thread. Read `body` (and `translatedBody` when you need it in Chinese). - `media`: nothing readable as text (pictures only, or a video that is music over burned-in captions). Look at the images or watch the video through the signed `media` links; a model that takes video can be given the link directly. - `summary`: only a title and summary are stored; say so rather than guessing the rest. 4. Answer with where each fact came from: the item's `hubUrl`, and for videos the timestamp (`[03:12]`). 5. Write only when asked: `POST /collect` to save a link (`readLater: true` also puts it on 稍后读 / 稍后看, video or article), `POST /items/{id}/later` to mark or clear 稍后读 / 稍后看 on an item already collected (`{"readLater": false}` clears the mark and keeps the item), `POST /items/{id}/star`, `PUT /items/{id}/note`, `POST /flomo/memos` to write a memo to the owner's Flomo. Something to read or watch later is 稍后读 / 稍后看, not a todo; a todo about an item links it with `itemId`. Media: a signed `url` expires after an hour, so use it right away and never store it; to keep a file's address, store its `stableUrl` and fetch it with the key (scope `media:read`). On `429`, wait `Retry-After` seconds. On `403 insufficient_scope`, tell the user which scope the key is missing (`required`). ## Service callers: collect, then wait for a webhook A service (not a chat agent) that sends links and processes them later, e.g. splitting a video into clips: Callback webhooks (service callers): the owner can register an HTTPS endpoint for a key. Items that key collects through `POST /collect` then produce signed events: `item.collected` (fetched), then exactly one of `item.ready` (all processing done: for a video, the file is stored and the transcript is final) or `item.failed` (with `reason`). Deliveries follow Standard Webhooks (https://www.standardwebhooks.com): headers `webhook-id` (the event id; deduplicate on it), `webhook-timestamp` (unix seconds) and `webhook-signature` (`v1,` with the endpoint's `whsec_` secret, space-separated during a secret rotation). Answer 2xx within 10 seconds; anything else is retried for about two days (1 min, 5 min, 15 min, 1 h, 3 h, 6 h, 12 h, 24 h). Payloads carry ids and links only: fetch content, timeline and signed media with the key. Without an endpoint, poll `GET /items/{id}` until `processing.status` is `ready` or `failed`. 1. Ask the owner for its own key (scopes `collect:write`, `items:read`) and a callback webhook endpoint on that key. The owner registers it; you get a `whsec_` signing secret once. Store both as secrets, never in code. 2. `POST /collect` with `{"url": "...", "clientRef": ""}`. Keep the returned `itemId`; `webhookEndpoints` says whether a webhook will follow. 3. Receive `item.collected`, then exactly one of `item.ready` or `item.failed`. Verify the Standard Webhooks signature (`webhook-id`, `webhook-timestamp`, `webhook-signature`: `v1,` + base64 HMAC-SHA256 of `id.timestamp.rawBody` keyed with the secret's base64-decoded bytes), refuse timestamps more than 5 minutes off, deduplicate on `webhook-id`, answer 2xx within 10 seconds and do the work afterwards. 4. On `item.ready`: read `GET /items/{id}/timeline?format=json` (final) and `GET /items/{id}/content` for media: download from `stableUrl` with the key (scope `media:read`) whenever you like, or from the signed `url` within the hour. For a video, `item.ready` means the file is stored. 5. Without an endpoint, poll `GET /items/{id}` at most once a minute until `processing.status` is `ready` or `failed`. Events may arrive out of order or more than once; `item.ready` implies collected. Failed deliveries are retried for about two days. ## Completion standard An answer built on this library names the items it used (title and hubUrl), quotes or paraphrases what they say with timestamps for video, and says plainly when the library has nothing on the question. ## Endpoints - GET https://pih-api.jiajun.fyi/search: Search the library (scope: search:read) - GET https://pih-api.jiajun.fyi/items: List items (scope: items:read) - GET https://pih-api.jiajun.fyi/shots: Videos laid out as shots (切片) (scope: items:read) - GET https://pih-api.jiajun.fyi/items/{id}: Get one item (scope: items:read) - GET https://pih-api.jiajun.fyi/items/{id}/content: Get an item's content (scope: items:read) - GET https://pih-api.jiajun.fyi/items/{id}/media/{mediaId}: Download one media file by its stable address (scope: media:read) - GET https://pih-api.jiajun.fyi/items/{id}/timeline: Read a video or episode as a timeline (scope: items:read) - PUT https://pih-api.jiajun.fyi/items/{id}/note: Set an item's note (scope: notes:write) - POST https://pih-api.jiajun.fyi/items/{id}/star: Star or unstar an item (scope: notes:write) - POST https://pih-api.jiajun.fyi/items/{id}/later: Mark or clear read / watch later (scope: notes:write) - POST https://pih-api.jiajun.fyi/collect: Collect a link (scope: collect:write) - POST https://pih-api.jiajun.fyi/flomo/memos: Write a memo to Flomo (scope: notes:write) - GET https://pih-api.jiajun.fyi/english/words: List English words (scope: english:read) - GET https://pih-api.jiajun.fyi/english/practice: List English practice records (scope: english:read) - GET https://pih-api.jiajun.fyi/songbook/songs: List songbook songs with their links (scope: songbook:read) - POST https://pih-api.jiajun.fyi/songbook/songs: Add a song to the songbook (scope: songbook:write) - POST https://pih-api.jiajun.fyi/songbook/score-takes: Save a recording and its detected notes (scope: songbook:write) - GET https://pih-api.jiajun.fyi/songbook/score-takes: List 扒谱结果 (takes saved from 实时扒谱) (scope: songbook:read) - GET https://pih-api.jiajun.fyi/songbook/score-takes/{id}: Read one 扒谱结果 with its MusicXML and lyrics (scope: songbook:read) - POST https://pih-api.jiajun.fyi/songbook/links/match: Match a batch of songbook links (scope: songbook:write) - PATCH https://pih-api.jiajun.fyi/songbook/songs/{key}/links/{service}: Set a song's link by hand (scope: songbook:write) - GET https://pih-api.jiajun.fyi/songbook/tracklists: List tracklists (scope: songbook:read) - POST https://pih-api.jiajun.fyi/songbook/tracklists: Ask for a 1001Tracklists set (scope: songbook:write) - GET https://pih-api.jiajun.fyi/songbook/tracklists/{id}: Read one tracklist (scope: songbook:read) - POST https://pih-api.jiajun.fyi/songbook/tracklists/{id}/reread: Read a stored set page again (scope: songbook:write) - GET https://pih-api.jiajun.fyi/songbook/sheets: List 图图乐谱 sheets (scope: songbook:read) - PATCH https://pih-api.jiajun.fyi/songbook/sheets/{key}: Change a song's 图图乐谱 sheet (scope: songbook:write) - POST https://pih-api.jiajun.fyi/things/wanted: Record something the owner wants to buy (记到想买) (scope: things:write) - GET https://pih-api.jiajun.fyi/things/products: Search 物品 (products) (scope: things:read) - GET https://pih-api.jiajun.fyi/things/wanted-webhook: Read the 想买 Webhook address (scope: things:write) - POST https://pih-api.jiajun.fyi/things/wanted-webhook: Make a new 想买 Webhook address (scope: things:write) - GET https://pih-api.jiajun.fyi/things/wanted.shortcut: Download the signed 记到想买 Shortcut (scope: things:write) - GET https://pih-api.jiajun.fyi/restaurants: Search 餐厅 (restaurants) (scope: restaurants:read) - POST https://pih-api.jiajun.fyi/restaurants: Add a restaurant (or find it) (scope: restaurants:write) - GET https://pih-api.jiajun.fyi/restaurants/{id}: Read one restaurant (scope: restaurants:read) - PATCH https://pih-api.jiajun.fyi/restaurants/{id}: Change a restaurant (scope: restaurants:write) - POST https://pih-api.jiajun.fyi/restaurants/{id}/visits: Record a visit (去吃了) (scope: restaurants:write) - POST https://pih-api.jiajun.fyi/restaurants/{id}/links: Link two stores (关联的店) (scope: restaurants:write) - PATCH https://pih-api.jiajun.fyi/restaurants/{id}/links/{linkId}: Confirm or remove a link (scope: restaurants:write) - GET https://pih-api.jiajun.fyi/restaurants/{id}/reviews: Read a restaurant's reviews (评价) (scope: restaurants:read) - PATCH https://pih-api.jiajun.fyi/restaurants/{id}/reviews: Pin or settle a review listing (scope: restaurants:write) - POST https://pih-api.jiajun.fyi/restaurants/{id}/reviews/refresh: Fetch a restaurant's reviews again (scope: restaurants:write) - GET https://pih-api.jiajun.fyi/books: List 读书 (WeRead books) (scope: books:read) - GET https://pih-api.jiajun.fyi/books/highlights: Search highlights and thoughts (划线、想法) (scope: books:read) - GET https://pih-api.jiajun.fyi/books/stats: Read 阅读时长 (reading time) (scope: books:read) - GET https://pih-api.jiajun.fyi/books/{id}: Read one book's notes (scope: books:read) - POST https://pih-api.jiajun.fyi/books/sync: Sync WeRead now (立即同步) (scope: books:write) - GET https://pih-api.jiajun.fyi/people: List 人物 (people) (scope: people:read) - POST https://pih-api.jiajun.fyi/people: Add a person (or find them) (scope: people:write) - GET https://pih-api.jiajun.fyi/people/{id}: Read one person and their items (scope: people:read) - PATCH https://pih-api.jiajun.fyi/people/{id}: Rename a person, or change aliases or description (scope: people:write) - POST https://pih-api.jiajun.fyi/people/{id}/merge: Merge two records of the same person (scope: people:write) - POST https://pih-api.jiajun.fyi/people/{id}/items: Link an item to a person (scope: people:write) - PATCH https://pih-api.jiajun.fyi/people/{id}/items/{itemId}: Change or remove a person's item (scope: people:write) - GET https://pih-api.jiajun.fyi/recipes: List 菜谱 (recipes) (scope: recipes:read) - POST https://pih-api.jiajun.fyi/recipes: Write your own recipe version for a saved post (scope: recipes:write) - GET https://pih-api.jiajun.fyi/recipes/{id}: Read one recipe (scope: recipes:read) - GET https://pih-api.jiajun.fyi/recipes/{id}/versions: List every version of a dish (scope: recipes:read) - PUT https://pih-api.jiajun.fyi/recipes/{id}/want: Mark 想做 (want to cook), or take it back (scope: recipes:write) - POST https://pih-api.jiajun.fyi/recipes/{id}/cooked: Log a 做过 (cooked it) (scope: recipes:write) - POST https://pih-api.jiajun.fyi/recipes/{id}/plan: Plan the dish for a day (排餐), or take it off (scope: recipes:write) - POST https://pih-api.jiajun.fyi/recipes/grocery: Add a line to the grocery list (采购清单) (scope: recipes:write) - POST https://pih-api.jiajun.fyi/recipes/import: Turn saved posts or videos into recipes (scope: recipes:write) - POST https://pih-api.jiajun.fyi/feedback: Report a problem, a missing capability or an idea (scope: any key) - GET https://pih-api.jiajun.fyi/feedback: List agent feedback (scope: feedback:read) - GET https://pih-api.jiajun.fyi/feedback/{id}: Read one report (by id or FB-12) with its logs and calls (scope: feedback:read) - PATCH https://pih-api.jiajun.fyi/feedback/{id}: Sort, resolve or merge a report (by id or FB-12) (scope: feedback:read) - GET https://pih-api.jiajun.fyi/todos: List 待办 (todos) (scope: todos:read) - POST https://pih-api.jiajun.fyi/todos: Add a todo (scope: todos:write) - PATCH https://pih-api.jiajun.fyi/todos/{id}: Change a todo, complete, drop or reopen it (scope: todos:write) - GET https://pih-api.jiajun.fyi/card-notes: List 卡片笔记 (card notes), newest first (scope: card_notes:read) - POST https://pih-api.jiajun.fyi/card-notes: Add a card note (scope: card_notes:write) - GET https://pih-api.jiajun.fyi/card-notes/tags: List the tags in the card box, with counts (scope: card_notes:read) - GET https://pih-api.jiajun.fyi/card-notes/{id}: Read one card note (scope: card_notes:read) - PATCH https://pih-api.jiajun.fyi/card-notes/{id}: Change a card note, or take it back (撤销) (scope: card_notes:write) - GET https://pih-api.jiajun.fyi/tutu/media: List 图图's photos and videos (scope: tutu:read) - GET https://pih-api.jiajun.fyi/tutu/media/{id}: Get one of 图图's photos or videos (scope: tutu:read) - GET https://pih-api.jiajun.fyi/tutu/days: List 图图's daycare days: arrival, pick-up and naps (scope: tutu:read) - PUT https://pih-api.jiajun.fyi/tutu/push-device: Turn new-photo notifications on or off for one device (scope: tutu:read) - GET https://pih-api.jiajun.fyi/tutu/home-logs: List 图图's home logs: sleep, wake-up, meals, poops, photos (scope: tutu:read) - POST https://pih-api.jiajun.fyi/tutu/home-logs: Log something at home: fell asleep, woke up, a meal, a poop, a photo (scope: tutu:write) - GET https://pih-api.jiajun.fyi/tutu/home-logs/{id}: Get one home log (scope: tutu:read) - PATCH https://pih-api.jiajun.fyi/tutu/home-logs/{id}: Change a home log, or take it back (撤销) (scope: tutu:write) - POST https://pih-api.jiajun.fyi/tutu/home-logs/{id}/photos: Add a photo to a home log (scope: tutu:write) - GET https://pih-api.jiajun.fyi/tutu/growth: List 图图's growth measurements (scope: tutu:read) - POST https://pih-api.jiajun.fyi/tutu/growth: Add a growth measurement (scope: health:write) - GET https://pih-api.jiajun.fyi/tutu/growth/chart: 图图's growth chart with WHO bands (scope: tutu:read) - GET https://pih-api.jiajun.fyi/tutu/health/records: List 图图's health records (scope: health:read) - POST https://pih-api.jiajun.fyi/tutu/health/records: Add a health record (scope: health:write) - GET https://pih-api.jiajun.fyi/tutu/health/records/{id}: Get one health record (scope: health:read) - PATCH https://pih-api.jiajun.fyi/tutu/health/records/{id}: Change a health record (scope: health:write) - GET https://pih-api.jiajun.fyi/tutu/health/vaccines: 图图's vaccines (scope: health:read) - GET https://pih-api.jiajun.fyi/connectors: How each 同步源 (sync) stands (scope: items:read) - POST https://pih-api.jiajun.fyi/notify: Tell the owner something (scope: notify:write) - POST https://pih-api.jiajun.fyi/tikhub: Make one TikHub request through the hub (scope: tikhub:call) - POST https://pih-api.jiajun.fyi/renders: Render a Blender scene (queued) (scope: renders:write) - GET https://pih-api.jiajun.fyi/renders/{id}: Read a render: status and progress (scope: renders:read) - GET https://pih-api.jiajun.fyi/renders/{id}/frames: List a render's frames (scope: renders:read) - GET https://pih-api.jiajun.fyi/renders/{id}/frames/{name}: Read one frame (scope: renders:read) ## Webhook events (PIH → your endpoint) - item.collected: Item collected: fetched, still processing - item.ready: Item ready: all processing done - item.failed: Item failed, with reason - webhook.test: Test event ## Docs - [OpenAPI 3.1 document](https://pih-api.jiajun.fyi/openapi.json): full request and response schemas - [Interactive reference](https://pih-api.jiajun.fyi/docs) - [All jiajun.fyi APIs](https://dev.jiajun.fyi/llms.txt)