{"status":"ok","service":"lark-http-hype","version":"3.4.0","apiVersion":"legacy","features":["table-management","field-management","record-crud","batch-ops","toon-format","caching","semantic-search","document-processing","image-proxy","drive-api","media-api","event-relay","freepik-webhook","zod-v3-validation"],"bundle":{"uncompressed_kb":304,"gzip_kb":57,"cf_free_limit_kb":1024,"usage_pct":"29%","zod_import":"zod/v3","note":"Well within CF free 1 MB limit."},"validation":{"library":"zod/v3","strategy":"parse at API boundary only — no 'as' casts inside handlers","on_error":"HTTP 422 { error: 'Validation failed: <field>: <message>' }","schemas":["FreepikRegisterSchema   — task_id, app_token, table_id, record_id, field_map?","FreepikWebhookSchema    — task_id, status (CREATED|IN_PROGRESS|COMPLETED|FAILED|CANCELLED), result?","RecordFieldsSchema      — { fields: Record<string,unknown> }","RecordSearchSchema      — app_token, table_id, filter?, sort?, page?","BatchGetSchema          — record_ids[] (1–100)","BatchCreateSchema       — records[{fields}][] (1–500)","BatchUpdateSchema       — records[{record_id,fields}][] (1–500)","BatchDeleteSchema       — records: string[] (1–500)","DriveCreateFolderSchema — name, folder_token?","DriveImportSchema       — file_extension, file_token, type, point","MediaBatchUrlSchema     — file_tokens (array|csv), src_type?","LarkEventSchema         — passthrough, validates envelope shape","UpdateFieldSchema       — field_name(req), type(int,req), property?, ui_type?, description?{text?,disable_sync?}","CreateFieldSchema       — field_name(req), type(int,req), property?, ui_type?, description?{text?,disable_sync?}","FieldPropertySchema     — options[], formatter, date_formatter, auto_fill, multiple, table_id, table_name, back_field_name, auto_serial, location, formula_expression, formula_type, allowed_edit_modes, currency_code, rating, range_customize, min, max","FieldDescriptionSchema  — text?, disable_sync? (false=sync to form field, true=block sync — only on POST/PUT)","CreateTableSchema           — app_token(req), table_name(req), fields?[TableFieldSchema], description?","RenameTableSchema           — name(req)","BatchCreateTablesSchema     — app_token(req), tables[{table_name,fields?,description?}][] (1–500)","BatchDeleteTablesSchema     — app_token(req), table_ids: string[] (1–500)","BatchUpdateTablesSchema     — app_token(req), tables[{table_id,name}][] (1–500)","CopyTableSchema             — app_token(req), table_id(req), name?, without_content?(bool)","CreateViewSchema            — view_name(req), view_type?","UpdateViewSchema            — view_name?, property?","Formula functions (47 verified) — Math: SUM,AVERAGE,MAX,MIN,ABS,ROUND,ROUNDUP,ROUNDDOWN,CEILING,FLOOR,MOD,POWER,SQRT,INT,LOG,VALUE,+ | Text: LEN,LEFT,RIGHT,MID,UPPER,LOWER,TRIM,REPLACE,CONCATENATE,CONTAINS,TEXT,ENCODE_URL_COMPONENT,ARRAYJOIN | Logic: IF,AND,OR,NOT,SWITCH,ISBLANK | Date: TODAY,NOW,YEAR,MONTH,DAY,WEEKDAY,DATEADD,DATEDIF | Aggregate: COUNTA,COUNTIF,SUMIF","Formula % rule              — formatter '0.00%': raw 0.014 displays as 1.40% (Lark ×100). formatter '0.00': raw 0.014 displays as 0.01"]},"cache":{"keys":1,"ttl":60},"auth":{"mode":"🔓 open — no Authorization header needed (API_KEY secret not set)","header":"none required","401 Unauthorized means":"API_KEY is set and your Authorization header is missing or wrong","403 Forbidden means":"ALLOWED_APP_TOKENS is set and your app_token is not in the list","422 Unprocessable means":"Request body failed Zod schema validation — check error.error field for field path","who holds Lark credentials":"This worker — callers never need LARK_APP_ID or LARK_APP_SECRET","what callers provide":"app_token + table_id per request (identifies which Lark Base/table — not auth)","allowed_app_tokens":"⚠️ open — all app_tokens accepted (set ALLOWED_APP_TOKENS to restrict)"},"agent_quickstart":{"base_url":"https://lark-http-hype.hypelive.workers.dev","auth_header":"none","schema contract":{"success":"{ data: T }","list":"{ data: T[], total: number, has_more?: boolean, page_token?: string }","error":"{ error: string, status: number }","record":"{ record_id: string, fields: Record<string, unknown> }"},"curl examples":{"list_records":"curl BASE/records/{app_token}/{table_id}","create_record":"curl -X POST BASE/records/{app_token}/{table_id} -H 'Content-Type: application/json' -d '{\"fields\":{\"Name\":\"value\"}}'","search_records":"curl -X POST BASE/records/search -H 'Content-Type: application/json' -d '{\"app_token\":\"bascXXX\",\"table_id\":\"tblXXX\",\"filter\":{...}}'","batch_media_url":"curl \"BASE/media/batch_url?file_tokens=tok1,tok2\"","freepik_register":"curl -X POST BASE/freepik/register -H 'Content-Type: application/json' -d '{\"task_id\":\"fp_xxx\",\"app_token\":\"bascXXX\",\"table_id\":\"tblXXX\",\"record_id\":\"recXXX\"}'","update_field":"curl -X PUT BASE/fields/{app_token}/{table_id}/{field_id} -H 'Content-Type: application/json' -d '{\"field_name\":\"person\",\"type\":11,\"property\":{\"multiple\":true}}'","update_field_with_description":"curl -X PUT BASE/fields/{app_token}/{table_id}/{field_id} -H 'Content-Type: application/json' -d '{\"field_name\":\"Status\",\"type\":3,\"description\":{\"text\":\"Current status\",\"disable_sync\":false}}'","list_tables":"curl BASE/tables?app_token=bascXXX","get_table":"curl BASE/tables/{app_token}/{table_id}","create_table":"curl -X POST BASE/tables -H 'Content-Type: application/json' -d '{\"app_token\":\"bascXXX\",\"table_name\":\"Orders\",\"fields\":[{\"field_name\":\"Name\",\"type\":1},{\"field_name\":\"Amount\",\"type\":2}]}'","batch_create_tables":"curl -X POST BASE/tables/batch_create -H 'Content-Type: application/json' -d '{\"app_token\":\"bascXXX\",\"tables\":[{\"table_name\":\"Table A\"},{\"table_name\":\"Table B\",\"fields\":[{\"field_name\":\"ID\",\"type\":1}]}]}'","rename_table":"curl -X PATCH BASE/tables/{app_token}/{table_id} -H 'Content-Type: application/json' -d '{\"name\":\"New Name\"}'","copy_table":"curl -X POST BASE/tables/copy -H 'Content-Type: application/json' -d '{\"app_token\":\"bascXXX\",\"table_id\":\"tblXXX\",\"name\":\"Copy of Table\"}'","delete_table":"curl -X DELETE BASE/tables/{app_token}/{table_id}","list_fields":"curl BASE/fields/{app_token}/{table_id}","create_field":"curl -X POST BASE/fields/{app_token}/{table_id} -H 'Content-Type: application/json' -d '{\"field_name\":\"Status\",\"type\":3,\"property\":{\"options\":[{\"name\":\"Active\",\"color\":3}]}}'","create_formula":"curl -X POST BASE/fields/{app_token}/{table_id} -H 'Content-Type: application/json' -d '{\"field_name\":\"Total\",\"type\":20,\"property\":{\"formula_expression\":\"SUM([Price],[Tax])\",\"formatter\":\"0.00\"}}'","list_views":"curl BASE/views/{app_token}/{table_id}","create_view":"curl -X POST BASE/views/{app_token}/{table_id} -H 'Content-Type: application/json' -d '{\"view_name\":\"Active Items\"}'","list_dashboards":"curl BASE/dashboards?app_token=bascXXX","copy_dashboard":"curl -X POST BASE/dashboards/copy -H 'Content-Type: application/json' -d '{\"app_token\":\"bascXXX\",\"block_id\":\"blkXXX\",\"name\":\"Copy\"}'"},"required fields per endpoint":{"/records/:app/:table (POST)":"{ fields: Record<string,unknown> }","/records/search (POST)":"{ app_token, table_id } — filter/sort/page_size optional","/records/batch_get (POST)":"{ app_token, table_id, record_ids: string[] }","/records/batch_create (POST)":"{ app_token, table_id, records: [{fields}][] }","/records/batch_update (POST)":"{ app_token, table_id, records: [{record_id,fields}][] }","/records/batch_delete (POST)":"{ app_token, table_id, records: string[] }","/fields/:app/:table (GET)":"— no body — path params only","/fields/:app/:table (POST)":"{ field_name, type(int), property?, ui_type?, description?: { text?, disable_sync? } }","/fields/:app/:table/:id (PUT)":"{ field_name, type(int), property?, ui_type?, description?: { text?, disable_sync? } } — type required always","/drive/folders (POST)":"{ name: string, folder_token?: string }","/drive/import (POST)":"{ file_extension, file_token, type, point }","/media/batch_url (POST)":"{ file_tokens: string[] | string, src_type?: string }","/freepik/register (POST)":"{ task_id, app_token, table_id, record_id, field_map? }","/tables (POST)":"CREATE table — { app_token, table_name, fields?, description? } → 201","/tables/:app_token/:table_id (GET)":"READ single table metadata → { data: { table_id, name, revision } }","/tables/:app_token/:table_id (PATCH)":"RENAME table — { name } → { data: { table_id, name } }","/tables/:app_token/:table_id (DELETE)":"DELETE single table (⚠️ irreversible) → { data: { table_id, deleted } }","/tables/copy (POST)":"COPY table — { app_token, table_id, name?, without_content? } → 201","/tables/batch_create (POST)":"BATCH CREATE — { app_token, tables: [{table_name, fields?, description?}] } → 201","/tables/batch_delete (POST)":"BATCH DELETE — { app_token, table_ids: string[] }","/tables/batch_update (POST)":"BATCH RENAME — { app_token, tables: [{table_id, name}] }","/views/:app/:table (GET)":"LIST views → { data: [], has_more, page_token, total }","/views/:app/:table (POST)":"CREATE view — { view_name, view_type? } → 201","/views/:app/:table/:view_id (GET)":"READ single view","/views/:app/:table/:view_id (PATCH)":"UPDATE view — { view_name?, filter_info?, sort_info?, group_info?, hidden_fields?, hierarchy_config? }","/views/:app/:table/:view_id (DELETE)":"DELETE view → { data: { view_id, deleted } }","[!] view filter/sort":"WRITE-ONLY — create/update accepts filter_info+sort_info, but GET returns property:null (Lark API limitation)","view_type options":"grid | kanban (needs group_info+SingleSelect) | gallery | gantt (needs DateTime) | form — only 5 types via API","filter operators":"is, isNot, isGreater, isGreaterEqual, isLess, isLessEqual, contains, doesNotContain, isEmpty, isNotEmpty, isBefore, isAfter","[!] isEmpty/isNotEmpty":"MUST use value:[] (empty array). NOT null, NOT [''], NOT omitted — Lark rejects all other formats","cross-table filtering":"Filter/sort on Lookup (type=19) and Formula (type=20) fields works as-if local. Lark resolves cross-table values server-side. Same operators.","[!] read vs write format":"5 types differ: User(write [{id}] not [{id,name}]), Attachment(write [{file_token}]), Link/DuplexLink(write ['recID'] not [{record_ids}]), Location(write {location,pname})","/dashboards?app_token= (GET)":"LIST dashboards → { data: [{block_id, name, share_config}] }","/dashboards/copy (POST)":"COPY dashboard — { app_token, block_id, name? } → 201"}},"endpoints":{"RESPONSE CONTRACT":{"Success shape":"{ data: T }  — data key ALWAYS present, never check ok/success","List shape":"{ data: T[], total?: number, has_more?: boolean, page_token?: string }","Error shape":"{ error: string, lark_code?: number }  — HTTP 4xx/5xx","Record type":"{ record_id: string, fields: Record<string, any> }","TOON format":"Add ?format=toon to ANY endpoint → response in TOON (30-60% fewer tokens). Header: X-Format: toon. Best for record arrays.","TOON example":"GET /tables?app_token=xxx&format=toon → compact tabular output","Field enrichment":"GET /fields responses add: type_name (e.g. 'SingleSelect'), color_name on options (e.g. 'LightBlue' for color:0). Write-safe: send color number, not name.","TOON date enrichment":"?format=toon adds _iso suffix for DateTime ms values (e.g. Tracking_Date_iso: '2026-02-14T17:00:00.000Z')"},"HTTP STATUS CODES":{"200 OK":"Success — read, update, delete, or no-op (Lark 1254606 DataNotChange)","201 Created":"Resource created — POST /tables, /tables/copy, /tables/batch_create, /views, /fields, /records","207 Multi-Status":"Partial success — POST /tables/batch_update (some renamed, some failed)","400 Bad Request":"Lark rejected request — invalid body, missing required fields, type mismatch","401 Unauthorized":"API_KEY is set but Authorization header missing or wrong","403 Forbidden":"app_token not in ALLOWED_APP_TOKENS allowlist, or Lark permission denied","404 Not Found":"Resource not found — wrong app_token, table_id, field_id, view_id, or record_id","409 Conflict":"Duplicate name — field or table name already exists (Lark 1254014)","422 Unprocessable":"Zod validation failed — check error field for details (e.g. missing required param)","429 Too Many Requests":"Lark rate limit or write conflict — retry after backoff","500 Internal Error":"Unexpected error — check error field for details","503 Service Unavailable":"Lark data not ready (1254607) — retry after 1-5s"},"LARK ERROR CODES → HTTP STATUS (16 codes mapped, verified 2026-03-26)":{"91402 → 404":"app_token NOTEXIST","1254003/1254040 → 404":"app_token or table not found","1254004 → 404":"table_id not found","1254005 → 404":"view_id not found","1254009/1254044 → 404":"field_id not found","1254030 → 404":"base not found or invalid page_token","1254043 → 404":"record_id not found","1254011 → 400":"invalid page_size (must >0)","1254000/1254001 → 400":"invalid request body","1254015 → 400":"field type/value mismatch","1254014/1254041 → 409":"duplicate field/table name","1254080-1254096 → 422":"property validation errors (Select, Date, Number, etc.)","1254301/1254302/1254304 → 403":"permission denied","99991672 → 403":"app lacks permission to base/table","1254290/1254291 → 429":"rate limit or write conflict","99991400 → 429":"global rate limit exceeded","1254606 → 200":"data not changed (no-op, treat as success)","1254607 → 503":"data not ready, retry after 1-5s"},"READ (cached, safe to retry)":{"cache":"GET /records list = 30s | single record = 60s | KOL/rates = 60s | images = 23h","GET /records/:app/:table":"List all records — ?page_size=&page_token=","GET /records/:app/:table/:id":"Single record by ID","POST /records/search":"Filter/sort/select — body: { app_token, table_id, filter?, field_names?, sort?, page_size?, page_token? }","POST /records/batch_get":"Fetch specific IDs — body: { app_token, table_id, record_ids: string[] }","GET /tables?app_token=":"List all tables in a base → { data: [{ table_id, name }] }","GET /tables/:app_token/:table_id":"Get single table → { data: { table_id, name, revision } }","GET /api/kols":"All KOLs (cached)","GET /api/kols/:id":"Single KOL","GET /api/campaigns":"All campaigns","GET /api/rate-cards|tier-rates|competitor-rates|...":"All rate endpoints","GET /drive/root":"Root folder meta","GET /drive/folders/:token/meta":"Folder meta","GET /drive/folders/:token/children":"Folder children","GET /drive/files":"List files in folder","GET /drive/files/:token":"Single file meta","POST /drive/files/batch_query":"Batch file meta","POST /drive/meta":"Batch doc meta (legacy)","GET /media/batch_url?file_tokens=":"Batch resolve public 24h URLs","POST /media/batch_url":"Same, POST form"},"WRITE (cache-invalidating, not idempotent)":{"invalidation":"All writes bust the list cache for their app_token+table_id","POST /records/:app/:table":"Create record — body: { fields } → 201","PUT /records/:app/:table/:id":"Replace record — body: { fields }","PATCH /records/:app/:table/:id":"Partial update — body: { fields }","DELETE /records/:app/:table/:id":"Delete record","POST /records/batch_create":"Bulk create — body: { app_token, table_id, records: [{fields}][] } → 201","POST /records/batch_update":"Bulk update — body: { app_token, table_id, records: [{record_id, fields}][] }","POST /records/batch_delete":"Bulk delete — body: { app_token, table_id, records: string[] }","POST /tables":"Create table — body: { app_token, table_name, fields?[{field_name,type,ui_type?,property?}] } → 201","POST /tables/batch_create":"Batch create tables — body: { app_token, tables: [{table_name, fields?}][] max 500 } → 201 { data: { table_ids: string[] } }","POST /tables/batch_delete":"Batch delete tables (⚠️ irreversible) — body: { app_token, table_ids: string[] max 500 } → 200 { data: { deleted: true, count: N } }","POST /tables/batch_update":"Batch rename tables (fan-out PATCH, parallel) — body: { app_token, tables: [{table_id, name}][] max 500 } → 200 { data: { updated: [{table_id,name}], failed: [{table_id,error}] } } | 207 partial | 422 all failed","GET /fields/:app/:table":"List fields — returns [{ field_id, field_name, type, ui_type, property, is_primary, is_hidden }]","POST /fields/:app/:table":"Create field → 201 — body: { field_name, type(int), property?, ui_type?, description?: { text?, disable_sync? } }","PUT /fields/:app/:table/:field_id":"Update field — body: { field_name, type(int), property?, ui_type?, description?: { text?, disable_sync? } } — type ALWAYS required even when only renaming","DELETE /fields/:app/:table/:field_id":"Delete field → { field_id, deleted: true }","POST /api/campaigns":"Create campaign → 201","PUT|DELETE /api/campaigns/:id":"Update/delete campaign","POST /drive/folders":"Create folder","POST /drive/files/:token/move":"Move file","POST /drive/files/:token/copy":"Copy file","DELETE /drive/files/:token":"Delete file ?type=","POST /drive/docs":"Create Lark Doc → 201","POST /drive/upload":"Upload file ≤20MB → 201","POST /drive/upload/prepare|part|finish":"Chunked file upload","POST /media/upload":"Upload media into doc ≤20MB → 201","POST /media/upload/prepare|part|finish":"Chunked media upload","POST /drive/import":"Import local file as Lark Doc/Sheet → 202"},"EVENTS & SUBSCRIPTIONS":{"POST /events":"Lark webhook receiver (HTTP mode) — handles url_verification, decrypts, verifies token","POST /events/callback":"Lark callback receiver — relays response body back to Lark within 5s","GET /events|/events/callback":"Describe webhook config","POST /drive/subscriptions/:token":"Subscribe to file events — body: { file_type, subscription_type? }","GET /drive/subscriptions/:token/:id":"Get subscription","PATCH /drive/subscriptions/:token/:id":"Toggle subscription"},"images":{"GET /files/:file_token/download":"Proxy image bytes from Lark Drive (streams image, handles auth + caching)","GET /files/:file_token":"Get temporary download URL as JSON","GET /api/image/:file_token":"Get temporary download URL as JSON (cached 23h)","GET /api/image/:file_token/redirect":"302 redirect to temporary image URL","GET /api/image/:file_token/resize?w=100&h=100&fit=cover":"302 redirect to resized image (w, h, fit: cover/contain/fill)","POST /api/images/batch":"Batch resolve up to 20 image URLs (body: {fileTokens: [...]} or {tokens: [...]})"},"kols":{"GET /api/kols":"List all KOLs","GET /api/kols/:id":"Get KOL by record ID","GET /api/kols/:id/related":"Get related KOLs","POST /api/kols/auto-categorize":"Auto-categorize KOLs using AI","GET /api/kols/live":"List live streaming KOLs","GET /api/kols/doctor":"List doctor/medical KOLs","GET /api/kols/doctor/:id":"Get doctor KOL by ID","GET /api/kols/beauty":"List beauty KOLs","GET /api/kols/beauty/:id":"Get beauty KOL by ID","GET /api/kols/tech":"List tech KOLs","GET /api/kols/tech/:id":"Get tech KOL by ID","GET /api/kols/niche":"List niche KOLs"},"campaigns":{"GET /api/campaigns":"List all campaigns","POST /api/campaigns":"Create a campaign","GET /api/campaigns/:id":"Get campaign by ID","PUT /api/campaigns/:id":"Update campaign by ID","DELETE /api/campaigns/:id":"Delete campaign by ID"},"liveSellers":{"GET /api/live-sellers":"List all live sellers","GET /api/live-sellers/live-now":"List currently live sellers"},"rates":{"GET /api/rate-cards":"KOL rate cards","GET /api/tier-rates":"Tier-based pricing rates","GET /api/competitor-rates":"Competitor pricing benchmarks","GET /api/platform-rates":"Per-platform rates (TikTok, IG, etc.)","GET /api/content-type-rates":"Rates by content type (video, live, post)","GET /api/industry-rates":"Rates by industry vertical","GET /api/usage-rights-rates":"Usage rights licensing rates","GET /api/market-benchmarks":"Market benchmark data","GET /api/ooh-media":"Out-of-home media inventory (?category=&vendor=&location=&search=)"},"agents":{"POST /api/agents/document-processor":"AI agent: process and extract structured data from documents","POST /api/agents/batch-updater":"AI agent: batch update records with AI-generated fields","POST /api/agents/batch-creator":"AI agent: batch create records from unstructured input"},"search":{"GET|POST /api/search":"Basic keyword search across KOLs (?q= or JSON body)","GET /api/search/semantic":"Semantic/AI-powered search (?q=&limit=)","GET /api/search/quick":"Quick autocomplete search (?q=)"},"cache":{"GET /api/cache/stats":"Show cache keys and count","POST /api/cache/clear":"Clear all cached entries"},"tables":{"── LIST ──":"","GET /tables?app_token=xxx":"List all tables in a base → { data: [{ table_id, name }], has_more, page_token, total } — supports ?page_size=&page_token=","── READ ──":"","GET /tables/:app_token/:table_id":"Get single table metadata → { data: { table_id, name, revision } }","── CREATE ──":"","POST /tables":"Create a NEW table in a base → 201 { data: { table_id, table_name, revision, default_view_id } }","POST /tables body":"{ app_token(req), table_name(req), fields?: [{ field_name, type(int), ui_type?, property? }], description?: string }","POST /tables notes":"Omit fields → Lark creates 1 default Text column. Max 200 fields. First field becomes primary. ⚠️ default_view_name rejected by Lark API (1254001).","POST /tables example":"curl -X POST BASE/tables -H 'Content-Type: application/json' -d '{\"app_token\":\"APP\",\"table_name\":\"Orders\",\"fields\":[{\"field_name\":\"Order ID\",\"type\":1},{\"field_name\":\"Status\",\"type\":3,\"property\":{\"options\":[{\"name\":\"Pending\",\"color\":5}]}},{\"field_name\":\"Amount\",\"type\":2,\"ui_type\":\"Currency\",\"property\":{\"currency_code\":\"THB\",\"formatter\":\"0.00\"}}]}'","── UPDATE ──":"","PATCH /tables/:app_token/:table_id":"Rename a table — body: { name(req) } → { data: { table_id, name } }","── DELETE ──":"","DELETE /tables/:app_token/:table_id":"Delete a single table (⚠️ irreversible) → { data: { table_id, deleted: true } }","── COPY ──":"","POST /tables/copy":"Duplicate a table → 201 { data: { table_id, name } } — body: { app_token, table_id, name?, without_content? }","── BATCH ──":"","POST /tables/batch_create":"Batch create up to 500 tables → 201 { data: { table_ids: string[] } } — body: { app_token, tables: [{ table_name, fields? }] }","POST /tables/batch_delete":"Batch delete up to 500 tables (⚠️ irreversible) → { data: { deleted: true, count } } — body: { app_token, table_ids: string[] }","POST /tables/batch_update":"Batch rename tables (fan-out PATCH) → { data: { updated, failed } } — body: { app_token, tables: [{ table_id, name }] }"},"fields":{"GET /fields/:app/:table":"List fields — response: { data: [FieldObject], total, has_more, page_token }","POST /fields/:app/:table":"Create field — body: { field_name, type(int), property?, ui_type?, description? } → 201 { data: FieldObject }","PUT /fields/:app/:table/:field_id":"Update field — body: { field_name, type(int), property?, ui_type?, description? } → 200 { data: FieldObject }","DELETE /fields/:app/:table/:field_id":"Delete field → 200 { data: { field_id, deleted: true } }"},"views":{"GET /views/:app/:table":"List views — { data: [ViewObject], has_more, page_token, total } — supports ?page_size=&page_token=","GET /views/:app/:table/:view_id":"Get single view → { data: ViewObject }","POST /views/:app/:table":"Create view → 201 { data: ViewObject } — body: { view_name, view_type? }","PATCH /views/:app/:table/:view_id":"Update view → { data: ViewObject } — body: { view_name?, property? }","DELETE /views/:app/:table/:view_id":"Delete view → { data: { view_id, deleted: true } }","FieldObject (actual response shape)":"{ field_id, field_name, type, ui_type, property, is_primary, is_hidden, is_extend, is_synced, description? }","[!] is_extend + is_synced":"Undocumented Lark fields returned in response — is_extend=false always, is_synced=false unless field comes from a synced table","field types (type int)":"1=Multiline 2=Number 3=SingleSelect 4=MultiSelect 5=Date 7=Checkbox 11=Person 13=Phone 15=URL 17=Attachment 18=OneWayLink 20=Formula 21=TwoWayLink 22=Location 23=Group 1001=CreatedTime 1002=ModifiedTime 1003=CreatedBy 1004=ModifiedBy 1005=AutoSerial","ui_types":"Text Email Barcode | Number Progress Currency Rating | SingleSelect MultiSelect | DateTime Checkbox | User GroupChat Phone Url Attachment | SingleLink Formula DuplexLink Location | CreatedTime ModifiedTime CreatedUser ModifiedUser AutoNumber","property.options (select/multi)":"{ id?, name, color(0-54) }[] — include id to update existing, omit id to add new. Lark auto-assigns id on creation.","property.formatter (Number/Currency/Progress)":"e.g. '0', '0.00', '0.0' — affects display only","property.currency_code":"ISO 4217 — e.g. 'THB', 'USD', 'EUR', 'CNY'","property.date_formatter (Date/CreatedTime/ModifiedTime)":"VALID formats tested: 'yyyy/MM/dd' | 'yyyy/MM/dd HH:mm' | 'yyyy-MM-dd' | 'MM/dd/yyyy'. INVALID: 'dd/MM/yyyy HH:mm' → 1254084","property.auto_fill (Date)":"boolean — auto-fill new records with creation timestamp","property.multiple (Person/Link)":"boolean — Person(11): allow multiple people | OneWayLink(18)/TwoWayLink(21): allow multiple records","property.range_customize + min + max (Progress/Rating)":"range_customize=true enables custom min/max. Rating: min/max control star count. NOTE: range_customize NOT returned in response for Rating.","property.rating.symbol":"'star' — only supported value","property.auto_serial":"{ type: 'custom'|'auto_increment_number', options?: [{type: 'system_number'|'fixed_text'|'created_time', value}][] }","property.location":"{ input_type: 'only_mobile'|'not_limit' }","property.formula_expression":"Formula string e.g. 'VALUE([Budget]) * 1.07' or 'SUM(bitable::$table[tblXXX].$field[fldXXX], ...)'","property.allowed_edit_modes":"{ manual: bool, scan: bool } — for Barcode ui_type","property.type (Formula output)":"{ data_type: int, ui_type?: 'Number'|'Progress'|'Currency'|'Rating'|'DateTime', ui_property?: {...} }","description body":"{ text?: string, disable_sync?: boolean } — disable_sync: false = sync description to form field ✅ (default) | true = block sync 🚫. Only active on POST/PUT.","errors":"400 body/name invalid | 404 field_id/app_token/table_id not found | 409 field name duplicate | 422 Zod validation (missing type, invalid ui_type) | 429 rate limit or write conflict | 500 internal","lark_code in error responses":"1254082=SingleSelectPropertyError 1254084=DatePropertyError 1254081=NumberPropertyError 1254044=FieldNotFound 1254014=NameDuplicate 1254015=TypeValueMismatch 1254606=DataNotChange(returns HTTP200)","HTTP 200 + error=DataNotChange":"Lark returned code 1254606 — field already has those exact values, request was idempotent (no-op). Treat as success.","⚠️ LIVE-TESTED behaviors (2026-03-14, table XwE7b1qQWaJNmksVyIUlBnw6gKd)":"① type REQUIRED even for rename-only ② Lark ALLOWS type changes (Text↔Number tested) — data loss risk, use caution ③ PRIMARY FIELD type change also allowed (is_primary=true field, Text→Number tested OK) ④ No-change PUT returns HTTP 200 {error:DataNotChange} ⑤ Options with corrupted IDs → 1254082 — delete+recreate the field ⑥ delete option by OMITTING it from options array — confirmed working ⑦ add option by including entry WITHOUT id — Lark auto-assigns id ⑧ All CF 1101 crashes fixed: was caused by HTTP 304 with JSON body — remapped to 200","is_primary behavior":"is_primary=true field: type change IS allowed by Lark API. Cannot change WHICH field is primary (read-only). To change primary field, update its type via PUT.","curl example (rename)":"curl -X PUT BASE/fields/{app}/{tbl}/{fld} -H 'Content-Type: application/json' -d '{\"field_name\":\"New Name\",\"type\":2}'","curl example (currency)":"curl -X PUT BASE/fields/{app}/{tbl}/{fld} -H 'Content-Type: application/json' -d '{\"field_name\":\"Budget\",\"type\":2,\"ui_type\":\"Currency\",\"property\":{\"currency_code\":\"THB\",\"formatter\":\"0.00\"}}'","curl example (select + add option)":"curl -X PUT BASE/fields/{app}/{tbl}/{fld} -H 'Content-Type: application/json' -d '{\"field_name\":\"Status\",\"type\":3,\"property\":{\"options\":[{\"id\":\"optXXX\",\"name\":\"Active\",\"color\":3},{\"name\":\"NewOption\",\"color\":10}]}}'"},"debug":{"GET /api/debug/tables":"List all Lark Base tables (legacy, use GET /tables)","GET /api/debug/kol":"Dump first raw KOL record (schema inspection)"},"drive":{"GET /drive/root":"Get root folder metadata","GET /drive/folders/:token/meta":"Get folder metadata","POST /drive/folders":"Create folder — body: { name, folder_token (parent) }","GET /drive/files":"List files in folder — ?folder_token=&page_size=&page_token=&order_by=&direction=","GET /drive/folders/:token/children":"List folder children (legacy) — ?type=&page_size=&page_token=","POST /drive/meta":"Batch get file metadata — body: { docs: [{token, type}] } (up to 200)","GET /drive/files/:token":"Get single file metadata","POST /drive/files/batch_query":"Batch get file metadata (new) — body: { file_tokens: string[] }","POST /drive/files/:token/move":"Move file — body: { type, folder_token }","POST /drive/files/:token/copy":"Copy file — body: { name, type, folder_token }","DELETE /drive/files/:token":"Delete file — ?type=doc|sheet|bitable|file|folder|shortcut","POST /drive/docs":"Create online Lark Doc — body: { title?, folder_token }","POST /drive/search":"Search Drive files — body: { search_key, count?, offset?, docs_types? }","POST /drive/upload":"Upload file (≤20MB) — multipart/form-data: file_name, parent_type, parent_node, size, file","POST /drive/upload/prepare":"Prepare multipart upload — body: { file_name, parent_node, size }","POST /drive/upload/part":"Upload a chunk — multipart: upload_id, seq, size, file","POST /drive/upload/finish":"Finalize upload — body: { upload_id, block_num }","GET /drive/files/:token/download":"Stream file bytes from Drive (proxied, requires worker auth) — Cache-Control: private, max-age=300","POST /drive/import":"Create import task (xlsx→sheet, docx→doc) — body: { file_extension, file_token, type, point }","GET /drive/import/:ticket":"Get import task status"},"media":{"WHAT IS MEDIA":"Images/files embedded INSIDE docs/sheets/bitable — NOT Drive folder files","parent_type values":"doc_image | docx_image | sheet_image | bitable_image | bitable_file | minutes_image | message_image | opendoc_image","POST /media/upload":"All-in-one upload ≤20MB — multipart/form-data fields: file_name(text), parent_type(text), parent_node(text), size(text), file(binary), checksum?(text MD5)","MULTIPART FLOW (>20MB)":"prepare → [part × block_num] → finish","POST /media/upload/prepare":"Start chunked session — body: { file_name, parent_type, parent_node, size } → { upload_id, block_size, block_num }. block_size = chunk size Lark wants. block_num = ceil(size/block_size)","POST /media/upload/part":"Send one chunk (repeat block_num times) — multipart: upload_id(text), seq(text, 0-based), size(text, this chunk bytes), file(binary), checksum?(text MD5 of chunk)","POST /media/upload/finish":"Finalize — body: { upload_id, block_num } → { file_token }","GET /media/:token/download":"Stream media bytes (proxied, requires worker auth) — Cache-Control: private, max-age=300. Use batch_url for embeddable public src","POST /media/batch_url":"Batch resolve file_tokens → PUBLIC 24h Lark CDN URLs (no auth on returned URLs) — body: { file_tokens: string[], src_type?: 'bitable'|'message' } → { urls: {token,url}[], cached, fetched, expires_in: '24h' }","GET /media/batch_url":"Same as POST — ?file_tokens=a,b,c&src_type=bitable → server-cached 23h so repeated calls are free","src_type guide":"bitable → bitable cell attachments | message → IM images | omit → doc/sheet/wiki/docx images","24h token note":"Returned URLs are public Lark CDN links valid 24h. Cache them on your side — calling this endpoint repeatedly is fine (23h server cache)."},"subscriptions":{"POST /drive/subscriptions/:file_token":"Subscribe to file events — body: { file_type, subscription_type?, is_subscribe? }","GET /drive/subscriptions/:file_token/:id":"Get subscription — ?file_type=","PATCH /drive/subscriptions/:file_token/:id":"Toggle subscription — body: { is_subscribe, file_type }"},"events":{"webhook URL":"https://lark-http-hype.hypelive.workers.dev/webhook  (alias: /events)","POST /webhook":"Lark push event receiver — decrypts (AES-256-CBC), verifies token, routes by header.app_id via EVENT_RELAY_MAP","POST /events":"Alias of /webhook","POST /events/callback":"Lark callback receiver — awaits downstream response and relays back to Lark within 5s","GET /webhook|/events|/events/callback":"Describe endpoint config + registered relay map","url_verification":"Responds to Lark challenge automatically — no config needed","encryption":"✅ AES-256-CBC enabled","relay":"⚠️ not set — events received but not forwarded"},"freepik":{"POST /freepik/register":"Register task_id → Lark record mapping before creating Freepik task — body: { task_id, app_token, table_id, record_id, field_map? }","POST /freepik/webhook":"Freepik completion webhook — verifies HMAC-SHA256 signature, updates Lark record, notifies WS hub","GET /freepik/webhook":"Describe Freepik webhook config including fallback settings","webhook URL":"https://lark-http-hype.hypelive.workers.dev/freepik/webhook","signature":"✅ HMAC-SHA256 enabled (webhook-signature header)","ws_hub":"✅ notifying wss://freepik-mcp.hypelive.app/ws","lark_fields":"freepik_status, freepik_result, freepik_urls (override per task via field_map in /register)","flow":"Studio → POST /freepik/register → create Freepik task → Freepik fires /freepik/webhook → worker updates Lark + notifies WS hub → Studio UI updates","fallback":"✅ enabled — parallel search 6 tables if webhook arrives before /register","status_values":["CREATED","IN_PROGRESS","COMPLETED","FAILED","CANCELLED"]}}}