{"openapi":"3.1.0","info":{"title":"Medialyst.ai API","description":"Development documentation","version":"1.0.0"},"servers":[{"url":"https://medialyst.ai","description":"API server"}],"paths":{"/api/health":{"get":{"responses":{"200":{"description":"OK"}},"operationId":"getApiHealth","tags":["Health"],"parameters":[],"summary":"Health check","description":"Returns 200 if the server is healthy"}},"/api/v1/media-lists":{"get":{"responses":{"200":{"description":"A filtered page of media lists","content":{"application/json":{"schema":{"type":"object","properties":{"media_lists":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"row_count":{"type":"integer","minimum":0},"column_count":{"type":"integer","minimum":0},"status":{"type":"string"},"project":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"created_at":{"type":["string","null"],"format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"}},"required":["id","name","description","row_count","column_count","status","project","created_at","updated_at"]}},"page":{"type":"object","properties":{"total":{"type":"integer","minimum":0},"next_cursor":{"type":["integer","null"],"minimum":0}},"required":["total","next_cursor"]}},"required":["media_lists","page"]}}}},"400":{"description":"Invalid filters or datetime bounds"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope"},"404":{"description":"Project not found"}},"operationId":"getApiV1Media-lists","tags":["Media Lists"],"parameters":[{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":24}},{"in":"query","name":"cursor","schema":{"type":"integer","minimum":0,"default":0}},{"in":"query","name":"created_after","schema":{"type":"string","format":"date-time"}},{"in":"query","name":"created_before","schema":{"type":"string","format":"date-time"}},{"in":"query","name":"updated_after","schema":{"type":"string","format":"date-time"}},{"in":"query","name":"updated_before","schema":{"type":"string","format":"date-time"}},{"in":"query","name":"project_id","schema":{"type":"string","minLength":1,"maxLength":255}}],"summary":"List media lists","description":"List organization-scoped media lists with offset-cursor paging and optional exclusive created/updated datetime bounds. Results are ordered by created_at descending, then id descending for deterministic paging. Filter the Default project with project_id=general or its backing project id; both match NULL-backed Default-project lists."}},"/api/v1/media-lists/delete":{"post":{"responses":{"200":{"description":"Deletion preview, receipt, or replay","content":{"application/json":{"schema":{"type":"object","properties":{"operation":{"type":"string","const":"delete"},"dry_run":{"type":"boolean"},"idempotent_replay":{"type":"boolean"},"matched_count":{"type":"integer","minimum":0},"deleted_count":{"type":"integer","minimum":0},"lists":{"type":"array","items":{"type":"object","properties":{"media_list_id":{"type":"string"},"status":{"type":"string","enum":["would_delete","deleted"]}},"required":["media_list_id","status"],"additionalProperties":false},"maxItems":50}},"required":["operation","dry_run","idempotent_replay","matched_count","deleted_count","lists"],"additionalProperties":false}}}},"400":{"description":"Invalid selector or retry key"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope"},"404":{"description":"One or more media lists not found"},"409":{"description":"Idempotency conflict"}},"operationId":"postApiV1Media-listsDelete","tags":["Media Lists"],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"selector":{"type":"object","properties":{"keys":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"maxItems":50}},"required":["keys"],"additionalProperties":false},"dry_run":{"type":"boolean","default":false},"idempotency_key":{"type":"string","minLength":8,"maxLength":255}},"required":["selector","idempotency_key"],"additionalProperties":false}}}},"summary":"Delete media lists","description":"Permanently delete up to 50 organization-scoped media lists selected by key, or validate the selector with dry_run=true. Non-dry-run requests are durably idempotent and cancel linked active jobs. Deletion cannot be undone."}},"/api/v1/media-lists/{mediaListId}":{"get":{"responses":{"200":{"description":"Media-list metadata, columns, and optional row values","content":{"application/json":{"schema":{"type":"object","properties":{"media_list":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string"},"columns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"workflowType":{"type":"string"},"dependencies":{"type":"array","items":{"type":"string"}}},"required":["id","name","workflowType"],"additionalProperties":true}},"schema_omitted":{"type":"boolean"},"settings":{"type":"object","additionalProperties":{}},"row_count":{"type":"integer","minimum":0},"project":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"created_at":{"type":["string","null"],"format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"}},"required":["id","name","description","status","columns","schema_omitted","settings","row_count","project","created_at","updated_at"]},"rows":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"position":{"type":"integer"},"values":{"type":"object","additionalProperties":{}},"data":{"type":"object","additionalProperties":{}},"origin":{"type":["object","null"],"additionalProperties":{}},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","position","values"]}},"page":{"type":"object","properties":{"next_cursor":{"type":["integer","null"],"minimum":0}},"required":["next_cursor"]}},"required":["media_list","rows","page"]}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope"},"404":{"description":"Media list not found"}},"operationId":"getApiV1Media-listsByMediaListId","tags":["Media Lists"],"parameters":[{"in":"query","name":"include_rows","schema":{"type":"boolean","default":false}},{"in":"query","name":"include_schema","schema":{"type":"boolean","default":false}},{"in":"query","name":"row_detail","schema":{"type":"string","enum":["preview","full"],"default":"preview"}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"in":"query","name":"cursor","schema":{"type":"integer","minimum":0,"default":0}},{"schema":{"type":"string"},"in":"path","name":"mediaListId","required":true}],"summary":"Get a media list","description":"Read the organization-scoped media-list table, including its resolved project. For website-equivalent completed rows, use include_rows=true, row_detail=full, and paginate with page.next_cursor. The response maps every returned column id to its row value and restores contact values persisted before contact masking was removed. include_schema=false (the default) returns safe column identity/type metadata without execution configuration."},"delete":{"responses":{"204":{"description":"Generated empty response"}},"operationId":"deleteApiV1Media-listsByMediaListId","tags":["Media Lists"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"mediaListId","required":true}],"summary":"Delete a media list","description":"Backward-compatible single-list adapter. Permanently delete an organization-scoped media list and cancel any linked active job. Send a stable Idempotency-Key header so a lost response can be retried safely. This cannot be undone."}},"/api/v1/projects":{"get":{"responses":{"200":{"description":"Projects in the authenticated organization"},"400":{"description":"Invalid request, or an attempt to delete the Default project, which cannot be deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope or plan upgrade required"},"404":{"description":"Project or file not found"},"409":{"description":"Version or resource conflict"},"429":{"description":"Rate limited"}},"operationId":"getApiV1Projects","tags":["Projects"],"parameters":[],"summary":"List projects","description":"List active projects with file, media-list, and memory counts. The default project uses the stable id general and is flagged with isDefault; it can be renamed but not archived or deleted."},"post":{"responses":{"201":{"description":"Project created"},"400":{"description":"Invalid request, or an attempt to delete the Default project, which cannot be deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope or plan upgrade required"},"404":{"description":"Project or file not found"},"409":{"description":"Version or resource conflict"},"429":{"description":"Rate limited"}},"operationId":"postApiV1Projects","tags":["Projects"],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":["string","null"],"maxLength":2000}},"required":["name"]}}}},"summary":"Create a project"}},"/api/v1/projects/{projectId}/files:upload-text":{"post":{"responses":{"201":{"description":"Text file stored and extraction started"},"400":{"description":"Invalid request, or an attempt to delete the Default project, which cannot be deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope or plan upgrade required"},"404":{"description":"Project or file not found"},"409":{"description":"Version or resource conflict"},"429":{"description":"Rate limited"}},"operationId":"postApiV1ProjectsByProjectIdFiles:upload-text","tags":["Projects"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200},"content":{"type":"string","minLength":1},"mimeType":{"type":"string","enum":["text/markdown","text/plain"]},"clientUploadKey":{"type":"string","minLength":1,"maxLength":64}},"required":["title","content"],"additionalProperties":false}}}},"summary":"Upload a text project file in one call","description":"Upload UTF-8 Markdown or plain text up to 4 MB. A title without a known project-file extension gets .md or .txt from mimeType, even when the human-readable title contains a dot; when mimeType is omitted, .txt selects text/plain, .md/.markdown selects text/markdown, and other titles default to Markdown. Medialyst stores the bytes, marks the file extracting, and starts safe extraction; poll the file endpoint until ready or failed. Send a clientUploadKey and reuse it on retries so a lost response cannot create a duplicate file."}},"/api/v1/projects/{projectId}/memory":{"get":{"responses":{"200":{"description":"Current Markdown memory document"},"400":{"description":"Invalid request, or an attempt to delete the Default project, which cannot be deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope or plan upgrade required"},"404":{"description":"Project or file not found"},"409":{"description":"Version or resource conflict"},"429":{"description":"Rate limited"}},"operationId":"getApiV1ProjectsByProjectIdMemory","tags":["Projects"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true}],"summary":"Get project memory"},"put":{"responses":{"200":{"description":"Updated memory document"},"400":{"description":"Invalid request, or an attempt to delete the Default project, which cannot be deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope or plan upgrade required"},"404":{"description":"Project or file not found"},"409":{"description":"Version or resource conflict"},"429":{"description":"Rate limited"}},"operationId":"putApiV1ProjectsByProjectIdMemory","tags":["Projects"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"markdown":{"type":"string","maxLength":20000},"expectedVersion":{"type":"integer","minimum":0},"expectedUpdatedAt":{"type":["string","null"],"format":"date-time"}},"required":["markdown","expectedVersion"]}}}},"summary":"Replace project memory","description":"Replace the full Markdown document using compare-and-set. expectedVersion must equal the current version or the API returns PROJECT_MEMORY_VERSION_CONFLICT."}},"/api/v1/projects/{projectId}/memory/lines":{"post":{"responses":{"200":{"description":"Updated memory document"},"400":{"description":"Invalid request, or an attempt to delete the Default project, which cannot be deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope or plan upgrade required"},"404":{"description":"Project or file not found"},"409":{"description":"Version or resource conflict"},"429":{"description":"Rate limited"}},"operationId":"postApiV1ProjectsByProjectIdMemoryLines","tags":["Projects"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"section":{"type":"string","enum":["About the client","Ranking preferences","Never","Pitch voice"]},"text":{"type":"string","minLength":1,"maxLength":300}},"required":["section","text"],"additionalProperties":false}}}},"summary":"Append one project-memory line","description":"Append one durable line to About the client, Ranking preferences, Never, or Pitch voice. Ranking preferences and Never require a reason after a colon. Lines are capped at 300 characters and retain API-key provenance."}},"/api/v1/projects/{projectId}/files":{"get":{"responses":{"200":{"description":"Project file summaries"},"400":{"description":"Invalid request, or an attempt to delete the Default project, which cannot be deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope or plan upgrade required"},"404":{"description":"Project or file not found"},"409":{"description":"Version or resource conflict"},"429":{"description":"Rate limited"}},"operationId":"getApiV1ProjectsByProjectIdFiles","tags":["Projects"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true}],"summary":"List project files"},"post":{"responses":{"201":{"description":"Presigned upload created"},"400":{"description":"Invalid request, or an attempt to delete the Default project, which cannot be deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope or plan upgrade required"},"404":{"description":"Project or file not found"},"409":{"description":"Version or resource conflict"},"429":{"description":"Rate limited"}},"operationId":"postApiV1ProjectsByProjectIdFiles","tags":["Projects"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200},"mimeType":{"type":"string","enum":["application/pdf","application/vnd.openxmlformats-officedocument.wordprocessingml.document","text/plain","text/markdown"]},"byteSize":{"type":"integer","exclusiveMinimum":0,"maximum":4000000},"clientUploadKey":{"type":"string","minLength":1,"maxLength":64}},"required":["title","mimeType","byteSize"]}}}},"summary":"Create a presigned project-file upload","description":"Step 1 of the three-step binary upload flow: create the file, PUT the exact bytes to uploadUrl with the returned headers, then call the complete endpoint with the lowercase SHA-256 digest."}},"/api/v1/projects/{projectId}/files/{fileId}/complete":{"post":{"responses":{"200":{"description":"File accepted for extraction"},"400":{"description":"Invalid request, or an attempt to delete the Default project, which cannot be deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope or plan upgrade required"},"404":{"description":"Project or file not found"},"409":{"description":"Version or resource conflict"},"429":{"description":"Rate limited"}},"operationId":"postApiV1ProjectsByProjectIdFilesByFileIdComplete","tags":["Projects"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true},{"schema":{"type":"string"},"in":"path","name":"fileId","required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"sha256":{"type":"string","pattern":"^[a-f0-9]{64}$"}},"required":["sha256"]}}}},"summary":"Complete a project-file upload","description":"Step 3 of the presigned flow. Verify the stored byte count and SHA-256 digest, then start extraction."}},"/api/v1/projects/{projectId}/files/{fileId}":{"get":{"responses":{"200":{"description":"Project file status and details"},"400":{"description":"Invalid request, or an attempt to delete the Default project, which cannot be deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope or plan upgrade required"},"404":{"description":"Project or file not found"},"409":{"description":"Version or resource conflict"},"429":{"description":"Rate limited"}},"operationId":"getApiV1ProjectsByProjectIdFilesByFileId","tags":["Projects"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true},{"schema":{"type":"string"},"in":"path","name":"fileId","required":true}],"summary":"Get a project file","description":"Poll this endpoint while status is extracting. Ready files include their generated description; failed files include failureCode."},"delete":{"responses":{"200":{"description":"Project file deleted"},"400":{"description":"Invalid request, or an attempt to delete the Default project, which cannot be deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope or plan upgrade required"},"404":{"description":"Project or file not found"},"409":{"description":"Version or resource conflict"},"429":{"description":"Rate limited"}},"operationId":"deleteApiV1ProjectsByProjectIdFilesByFileId","tags":["Projects"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true},{"schema":{"type":"string"},"in":"path","name":"fileId","required":true}],"summary":"Delete a project file"}},"/api/v1/projects/{projectId}":{"get":{"responses":{"200":{"description":"Project details and counts"},"400":{"description":"Invalid request, or an attempt to delete the Default project, which cannot be deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope or plan upgrade required"},"404":{"description":"Project or file not found"},"409":{"description":"Version or resource conflict"},"429":{"description":"Rate limited"}},"operationId":"getApiV1ProjectsByProjectId","tags":["Projects"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true}],"summary":"Get a project"},"patch":{"responses":{"200":{"description":"Project updated"},"400":{"description":"Invalid request, or an attempt to delete the Default project, which cannot be deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope or plan upgrade required"},"404":{"description":"Project or file not found"},"409":{"description":"Version or resource conflict"},"429":{"description":"Rate limited"}},"operationId":"patchApiV1ProjectsByProjectId","tags":["Projects"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":["string","null"],"maxLength":2000}}}}}},"summary":"Update a project","description":"Update a project name and/or description."},"delete":{"responses":{"200":{"description":"Deleted or archived disposition"},"400":{"description":"Invalid request, or an attempt to delete the Default project, which cannot be deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope or plan upgrade required"},"404":{"description":"Project or file not found"},"409":{"description":"Version or resource conflict"},"429":{"description":"Rate limited"}},"operationId":"deleteApiV1ProjectsByProjectId","tags":["Projects"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true}],"summary":"Delete or archive a project","description":"Empty projects are deleted. Projects with files, media lists, campaigns, or agent history are archived so their lists remain reachable."}},"/api/v1/analytics":{"get":{"responses":{"200":{"description":"Pitch analytics summary","content":{"application/json":{"schema":{"type":"object","properties":{"summary":{"type":"object","properties":{"sent":{"type":"integer","minimum":0},"reply_tracked_sent":{"type":"integer","minimum":0},"delivered":{"type":"integer","minimum":0},"opened":{"type":"integer","minimum":0},"likely_human_opened":{"type":"integer","minimum":0},"clicked":{"type":"integer","minimum":0},"likely_human_clicked":{"type":"integer","minimum":0},"replied":{"type":"integer","minimum":0},"reply_messages":{"type":"integer","minimum":0},"accepted":{"type":"integer","minimum":0},"acceptance_denominator":{"type":"integer","minimum":0},"reply_labels":{"type":"object","properties":{"positive":{"type":"integer","minimum":0},"negative":{"type":"integer","minimum":0},"no_longer_at_outlet":{"type":"integer","minimum":0},"unsubscribe":{"type":"integer","minimum":0},"out_of_office":{"type":"integer","minimum":0},"bounce":{"type":"integer","minimum":0},"other":{"type":"integer","minimum":0}},"required":["positive","negative","no_longer_at_outlet","unsubscribe","out_of_office","bounce","other"]},"unclassified_replies":{"type":"integer","minimum":0},"rates":{"type":"object","properties":{"delivery":{"type":"number","minimum":0,"maximum":1},"open":{"type":"number","minimum":0,"maximum":1},"likely_human_open":{"type":"number","minimum":0,"maximum":1},"click":{"type":"number","minimum":0,"maximum":1},"likely_human_click":{"type":"number","minimum":0,"maximum":1},"reply":{"type":"number","minimum":0,"maximum":1},"acceptance":{"type":"number","minimum":0,"maximum":1}},"required":["delivery","open","likely_human_open","click","likely_human_click","reply","acceptance"]},"campaigns":{"type":"integer","minimum":0}},"required":["sent","reply_tracked_sent","delivered","opened","likely_human_opened","clicked","likely_human_clicked","replied","reply_messages","accepted","acceptance_denominator","reply_labels","unclassified_replies","rates","campaigns"]},"time_series":{"type":"array","items":{"type":"object","properties":{"bucket_start":{"type":"string"},"sent":{"type":"integer","minimum":0},"delivered":{"type":"integer","minimum":0},"opened":{"type":"integer","minimum":0},"likely_human_opened":{"type":"integer","minimum":0},"clicked":{"type":"integer","minimum":0},"likely_human_clicked":{"type":"integer","minimum":0},"replied":{"type":"integer","minimum":0},"accepted":{"type":"integer","minimum":0},"acceptance_denominator":{"type":"integer","minimum":0}},"required":["bucket_start","sent","delivered","opened","likely_human_opened","clicked","likely_human_clicked","replied","accepted","acceptance_denominator"]}},"breakdowns":{"type":"object","properties":{"projects":{"type":"array","items":{"type":"object","properties":{"project_id":{"type":"string"},"project_name":{"type":"string"},"campaigns":{"type":"integer","minimum":0},"metrics":{"type":"object","properties":{"sent":{"type":"integer","minimum":0},"reply_tracked_sent":{"type":"integer","minimum":0},"delivered":{"type":"integer","minimum":0},"opened":{"type":"integer","minimum":0},"likely_human_opened":{"type":"integer","minimum":0},"clicked":{"type":"integer","minimum":0},"likely_human_clicked":{"type":"integer","minimum":0},"replied":{"type":"integer","minimum":0},"reply_messages":{"type":"integer","minimum":0},"accepted":{"type":"integer","minimum":0},"acceptance_denominator":{"type":"integer","minimum":0},"reply_labels":{"type":"object","properties":{"positive":{"type":"integer","minimum":0},"negative":{"type":"integer","minimum":0},"no_longer_at_outlet":{"type":"integer","minimum":0},"unsubscribe":{"type":"integer","minimum":0},"out_of_office":{"type":"integer","minimum":0},"bounce":{"type":"integer","minimum":0},"other":{"type":"integer","minimum":0}},"required":["positive","negative","no_longer_at_outlet","unsubscribe","out_of_office","bounce","other"]},"unclassified_replies":{"type":"integer","minimum":0},"rates":{"type":"object","properties":{"delivery":{"type":"number","minimum":0,"maximum":1},"open":{"type":"number","minimum":0,"maximum":1},"likely_human_open":{"type":"number","minimum":0,"maximum":1},"click":{"type":"number","minimum":0,"maximum":1},"likely_human_click":{"type":"number","minimum":0,"maximum":1},"reply":{"type":"number","minimum":0,"maximum":1},"acceptance":{"type":"number","minimum":0,"maximum":1}},"required":["delivery","open","likely_human_open","click","likely_human_click","reply","acceptance"]}},"required":["sent","reply_tracked_sent","delivered","opened","likely_human_opened","clicked","likely_human_clicked","replied","reply_messages","accepted","acceptance_denominator","reply_labels","unclassified_replies","rates"]}},"required":["project_id","project_name","campaigns","metrics"]}},"media_lists":{"type":"array","items":{"type":"object","properties":{"media_list_id":{"type":"string"},"media_list_name":{"type":"string"},"campaigns":{"type":"integer","minimum":0},"metrics":{"type":"object","properties":{"sent":{"type":"integer","minimum":0},"reply_tracked_sent":{"type":"integer","minimum":0},"delivered":{"type":"integer","minimum":0},"opened":{"type":"integer","minimum":0},"likely_human_opened":{"type":"integer","minimum":0},"clicked":{"type":"integer","minimum":0},"likely_human_clicked":{"type":"integer","minimum":0},"replied":{"type":"integer","minimum":0},"reply_messages":{"type":"integer","minimum":0},"accepted":{"type":"integer","minimum":0},"acceptance_denominator":{"type":"integer","minimum":0},"reply_labels":{"type":"object","properties":{"positive":{"type":"integer","minimum":0},"negative":{"type":"integer","minimum":0},"no_longer_at_outlet":{"type":"integer","minimum":0},"unsubscribe":{"type":"integer","minimum":0},"out_of_office":{"type":"integer","minimum":0},"bounce":{"type":"integer","minimum":0},"other":{"type":"integer","minimum":0}},"required":["positive","negative","no_longer_at_outlet","unsubscribe","out_of_office","bounce","other"]},"unclassified_replies":{"type":"integer","minimum":0},"rates":{"type":"object","properties":{"delivery":{"type":"number","minimum":0,"maximum":1},"open":{"type":"number","minimum":0,"maximum":1},"likely_human_open":{"type":"number","minimum":0,"maximum":1},"click":{"type":"number","minimum":0,"maximum":1},"likely_human_click":{"type":"number","minimum":0,"maximum":1},"reply":{"type":"number","minimum":0,"maximum":1},"acceptance":{"type":"number","minimum":0,"maximum":1}},"required":["delivery","open","likely_human_open","click","likely_human_click","reply","acceptance"]}},"required":["sent","reply_tracked_sent","delivered","opened","likely_human_opened","clicked","likely_human_clicked","replied","reply_messages","accepted","acceptance_denominator","reply_labels","unclassified_replies","rates"]}},"required":["media_list_id","media_list_name","campaigns","metrics"]}},"pitches":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"subject":{"type":"string"},"status":{"type":"string","enum":["live","scheduled","done"]},"project_id":{"type":"string"},"media_list_id":{"type":"string"},"media_list_name":{"type":"string"},"provider":{"type":"string"},"sent_at":{"type":["string","null"],"format":"date-time"},"metrics":{"type":"object","properties":{"sent":{"type":"integer","minimum":0},"reply_tracked_sent":{"type":"integer","minimum":0},"delivered":{"type":"integer","minimum":0},"opened":{"type":"integer","minimum":0},"likely_human_opened":{"type":"integer","minimum":0},"clicked":{"type":"integer","minimum":0},"likely_human_clicked":{"type":"integer","minimum":0},"replied":{"type":"integer","minimum":0},"reply_messages":{"type":"integer","minimum":0},"accepted":{"type":"integer","minimum":0},"acceptance_denominator":{"type":"integer","minimum":0},"reply_labels":{"type":"object","properties":{"positive":{"type":"integer","minimum":0},"negative":{"type":"integer","minimum":0},"no_longer_at_outlet":{"type":"integer","minimum":0},"unsubscribe":{"type":"integer","minimum":0},"out_of_office":{"type":"integer","minimum":0},"bounce":{"type":"integer","minimum":0},"other":{"type":"integer","minimum":0}},"required":["positive","negative","no_longer_at_outlet","unsubscribe","out_of_office","bounce","other"]},"unclassified_replies":{"type":"integer","minimum":0},"rates":{"type":"object","properties":{"delivery":{"type":"number","minimum":0,"maximum":1},"open":{"type":"number","minimum":0,"maximum":1},"likely_human_open":{"type":"number","minimum":0,"maximum":1},"click":{"type":"number","minimum":0,"maximum":1},"likely_human_click":{"type":"number","minimum":0,"maximum":1},"reply":{"type":"number","minimum":0,"maximum":1},"acceptance":{"type":"number","minimum":0,"maximum":1}},"required":["delivery","open","likely_human_open","click","likely_human_click","reply","acceptance"]}},"required":["sent","reply_tracked_sent","delivered","opened","likely_human_opened","clicked","likely_human_clicked","replied","reply_messages","accepted","acceptance_denominator","reply_labels","unclassified_replies","rates"]}},"required":["id","name","subject","status","project_id","media_list_id","media_list_name","provider","sent_at","metrics"]}}},"required":["projects","media_lists","pitches"]},"filters":{"type":"object","properties":{"project_id":{"type":["string","null"]},"media_list_id":{"type":["string","null"]},"date_from":{"type":["string","null"]},"date_to":{"type":["string","null"]},"granularity":{"type":"string","enum":["day","week","month"]}},"required":["project_id","media_list_id","date_from","date_to","granularity"]},"page":{"type":"object","properties":{"limit":{"type":"integer","minimum":1,"maximum":50},"total":{"type":"integer","minimum":0},"truncated":{"type":"boolean"},"next_cursor":{"type":["string","null"]}},"required":["limit","total","truncated","next_cursor"]}},"required":["summary","time_series","breakdowns","filters","page"]}}}},"400":{"description":"Invalid filter or cursor"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope"},"404":{"description":"Pitch or media list not found"},"429":{"description":"Rate limited"}},"operationId":"getApiV1Analytics","tags":["Analytics"],"parameters":[{"in":"query","name":"project_id","schema":{"type":"string","minLength":1}},{"in":"query","name":"media_list_id","schema":{"type":"string","minLength":1}},{"in":"query","name":"date_from","schema":{"type":"string","minLength":1}},{"in":"query","name":"date_to","schema":{"type":"string","minLength":1}},{"in":"query","name":"granularity","schema":{"type":"string","enum":["day","week","month"]}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":50}},{"in":"query","name":"cursor","schema":{"type":"string","minLength":1,"maxLength":2048}}],"summary":"Get pitch analytics","description":"Return UI-parity pitch totals, UTC time-series buckets, and project, media-list, and pitch breakdowns. date_from and date_to select pitches by send time."}},"/api/v1/analytics/pitches/{pitchId}":{"get":{"responses":{"200":{"description":"Pitch analytics and paginated recipients","content":{"application/json":{"schema":{"type":"object","properties":{"pitch":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"subject":{"type":"string"},"status":{"type":"string","enum":["live","scheduled","done"]},"project_id":{"type":"string"},"media_list_id":{"type":"string"},"media_list_name":{"type":"string"},"provider":{"type":"string"},"sent_at":{"type":["string","null"],"format":"date-time"},"metrics":{"type":"object","properties":{"sent":{"type":"integer","minimum":0},"reply_tracked_sent":{"type":"integer","minimum":0},"delivered":{"type":"integer","minimum":0},"opened":{"type":"integer","minimum":0},"likely_human_opened":{"type":"integer","minimum":0},"clicked":{"type":"integer","minimum":0},"likely_human_clicked":{"type":"integer","minimum":0},"replied":{"type":"integer","minimum":0},"reply_messages":{"type":"integer","minimum":0},"accepted":{"type":"integer","minimum":0},"acceptance_denominator":{"type":"integer","minimum":0},"reply_labels":{"type":"object","properties":{"positive":{"type":"integer","minimum":0},"negative":{"type":"integer","minimum":0},"no_longer_at_outlet":{"type":"integer","minimum":0},"unsubscribe":{"type":"integer","minimum":0},"out_of_office":{"type":"integer","minimum":0},"bounce":{"type":"integer","minimum":0},"other":{"type":"integer","minimum":0}},"required":["positive","negative","no_longer_at_outlet","unsubscribe","out_of_office","bounce","other"]},"unclassified_replies":{"type":"integer","minimum":0},"rates":{"type":"object","properties":{"delivery":{"type":"number","minimum":0,"maximum":1},"open":{"type":"number","minimum":0,"maximum":1},"likely_human_open":{"type":"number","minimum":0,"maximum":1},"click":{"type":"number","minimum":0,"maximum":1},"likely_human_click":{"type":"number","minimum":0,"maximum":1},"reply":{"type":"number","minimum":0,"maximum":1},"acceptance":{"type":"number","minimum":0,"maximum":1}},"required":["delivery","open","likely_human_open","click","likely_human_click","reply","acceptance"]}},"required":["sent","reply_tracked_sent","delivered","opened","likely_human_opened","clicked","likely_human_clicked","replied","reply_messages","accepted","acceptance_denominator","reply_labels","unclassified_replies","rates"]}},"required":["id","name","subject","status","project_id","media_list_id","media_list_name","provider","sent_at","metrics"]},"time_series":{"type":"array","items":{"type":"object","properties":{"bucket_start":{"type":"string"},"sent":{"type":"integer","minimum":0},"delivered":{"type":"integer","minimum":0},"opened":{"type":"integer","minimum":0},"likely_human_opened":{"type":"integer","minimum":0},"clicked":{"type":"integer","minimum":0},"likely_human_clicked":{"type":"integer","minimum":0},"replied":{"type":"integer","minimum":0},"accepted":{"type":"integer","minimum":0},"acceptance_denominator":{"type":"integer","minimum":0}},"required":["bucket_start","sent","delivered","opened","likely_human_opened","clicked","likely_human_clicked","replied","accepted","acceptance_denominator"]}},"recipients":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"journalist":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string"},"outlet":{"type":"string"},"beat":{"type":"string"}},"required":["name","email","outlet","beat"]},"status":{"type":"string","enum":["bounced","sent","opened","clicked","replied"]},"provider":{"type":"string","enum":["gmail","outlook","unknown"]},"sent_at":{"type":"string","format":"date-time"},"first_open_at":{"type":["string","null"],"format":"date-time"},"last_activity_at":{"type":"string","format":"date-time"},"reply_tracking_eligible":{"type":"boolean"},"thread_url":{"type":["string","null"]},"metrics":{"type":"object","properties":{"opens":{"type":"integer","minimum":0},"likely_human_opens":{"type":"integer","minimum":0},"clicks":{"type":"integer","minimum":0},"likely_human_clicks":{"type":"integer","minimum":0},"replies":{"type":"integer","minimum":0}},"required":["opens","likely_human_opens","clicks","likely_human_clicks","replies"]},"opens":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"event_id":{"type":"string"},"occurred_at":{"type":"string","format":"date-time"},"label":{"type":"string"},"location":{"type":"string"},"country":{"type":["string","null"]},"asn":{"type":["string","null"]},"request_method":{"type":["string","null"]},"client":{"type":"string"},"bot_classification":{"type":"string"},"confidence":{"type":"number"},"reason_codes":{"type":"array","items":{"type":"string"}},"reason":{"type":"string"}},"required":["id","event_id","occurred_at","label","location","country","asn","request_method","client","bot_classification","confidence","reason_codes","reason"]}},"clicks":{"type":"array","items":{"type":"object","properties":{"occurred_at":{"type":"string","format":"date-time"},"label":{"type":"string"},"url":{"type":"string"},"bot_classification":{"type":"string"},"confidence":{"type":"number"},"reason_codes":{"type":"array","items":{"type":"string"}}},"required":["occurred_at","label","url","bot_classification","confidence","reason_codes"]}},"events":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"event_id":{"type":"string"},"type":{"type":"string"},"occurred_at":{"type":"string","format":"date-time"},"label":{"type":"string"},"location":{"type":"string"},"country":{"type":["string","null"]},"asn":{"type":["string","null"]},"request_method":{"type":["string","null"]},"client":{"type":"string"},"bot_classification":{"type":"string"},"confidence":{"type":"number"},"reason_codes":{"type":"array","items":{"type":"string"}},"reason":{"type":"string"},"tracked_link_id":{"type":["string","null"]},"link_label":{"type":["string","null"]},"url":{"type":["string","null"]}},"required":["id","event_id","type","occurred_at","label","location","country","asn","request_method","client","bot_classification","confidence","reason_codes","reason","tracked_link_id","link_label","url"]}},"replies":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"provider":{"type":"string"},"provider_thread_id":{"type":["string","null"]},"thread_url":{"type":["string","null"]},"sender_email":{"type":"string"},"sender_name":{"type":["string","null"]},"received_at":{"type":"string","format":"date-time"},"subject":{"type":"string"},"body_html":{"type":"string"},"attachment_count":{"type":"integer","minimum":0},"label":{"type":["string","null"],"enum":["positive","negative","no_longer_at_outlet","unsubscribe","out_of_office","bounce","other",null]},"classification_confidence":{"type":["number","null"],"minimum":0,"maximum":1},"classification_model":{"type":["string","null"]},"classification_needs_review":{"type":"boolean"},"label_source":{"type":["string","null"],"enum":["model","rule","user",null]},"classified_at":{"type":["string","null"],"format":"date-time"}},"required":["id","provider","provider_thread_id","thread_url","sender_email","sender_name","received_at","subject","body_html","attachment_count","label","classification_confidence","classification_model","classification_needs_review","label_source","classified_at"]}}},"required":["id","journalist","status","provider","sent_at","first_open_at","last_activity_at","reply_tracking_eligible","thread_url","metrics","opens","clicks","events","replies"]}},"page":{"type":"object","properties":{"limit":{"type":"integer","minimum":1,"maximum":50},"total":{"type":"integer","minimum":0},"truncated":{"type":"boolean"},"next_cursor":{"type":["string","null"]}},"required":["limit","total","truncated","next_cursor"]}},"required":["pitch","time_series","recipients","page"]}}}},"400":{"description":"Invalid filter or cursor"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope"},"404":{"description":"Pitch or media list not found"},"429":{"description":"Rate limited"}},"operationId":"getApiV1AnalyticsPitchesByPitchId","tags":["Analytics"],"parameters":[{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":50}},{"in":"query","name":"cursor","schema":{"type":"string","minLength":1,"maxLength":2048}},{"schema":{"type":"string"},"in":"path","name":"pitchId","required":true}],"summary":"Get one pitch's recipient analytics","description":"Return pitch metrics and the UI's per-recipient opens, clicks, tracking classifications, and reply thread details."}},"/api/v1/projects/{projectId}/radar":{"get":{"responses":{"200":{"description":"Radar, latest run, and plan limits"},"400":{"description":"Invalid RADAR.md or request body"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope, flag disabled, or plan limit"},"404":{"description":"Project not found"},"409":{"description":"Radar already exists"},"429":{"description":"Rate limited"}},"operationId":"getApiV1ProjectsByProjectIdRadar","tags":["Projects"],"parameters":[{"in":"query","name":"days","schema":{"type":"integer","minimum":1,"maximum":30,"default":1}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":50,"default":50}},{"in":"query","name":"cursor","schema":{"type":"string","minLength":1,"maxLength":2048}},{"schema":{"type":"string"},"in":"path","name":"projectId","required":true}],"summary":"Get a project Radar","description":"Returns RADAR.md to the authenticated agent on every plan; the file remains agent-managed when direct context editing is unavailable."},"put":{"responses":{"200":{"description":"Radar updated"},"400":{"description":"Invalid RADAR.md or request body"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope, flag disabled, or plan limit"},"404":{"description":"Project not found"},"409":{"description":"Radar already exists"},"429":{"description":"Rate limited"}},"operationId":"putApiV1ProjectsByProjectIdRadar","tags":["Projects"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"markdown":{"type":"string","minLength":1,"maxLength":20000},"expected_version":{"type":"integer","minimum":0}},"required":["markdown","expected_version"],"additionalProperties":false}}}},"summary":"Replace a project RADAR.md","description":"Agent-managed compare-and-set update. Read the current version first and send it as expected_version."},"patch":{"responses":{"200":{"description":"Radar settings updated"},"400":{"description":"Invalid RADAR.md or request body"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope, flag disabled, or plan limit"},"404":{"description":"Project not found"},"409":{"description":"Radar already exists"},"429":{"description":"Rate limited"}},"operationId":"patchApiV1ProjectsByProjectIdRadar","tags":["Projects"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["active","paused"]},"schedule_hour_local":{"type":"integer","minimum":0,"maximum":23},"email_digest_enabled":{"type":"boolean"},"email_cc":{"type":"array","items":{"type":"string","format":"email"},"maxItems":10},"slack_digest_enabled":{"type":"boolean"},"slack_webhook_url":{"anyOf":[{"type":"string","minLength":1,"maxLength":512},{"type":"string","const":""},{"type":"null"}]},"send_test":{"type":"boolean"}},"additionalProperties":false}}}},"summary":"Update project Radar settings","description":"Updates delivery or schedule settings. email_cc accepts up to 10 current organization-member email addresses; [] clears it. Radar responses return resolved member emails in delivery.email.cc."},"post":{"responses":{"201":{"description":"Radar created and optional run queued"},"400":{"description":"Invalid RADAR.md or request body"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope, flag disabled, or plan limit"},"404":{"description":"Project not found"},"409":{"description":"Radar already exists"},"429":{"description":"Rate limited"}},"operationId":"postApiV1ProjectsByProjectIdRadar","tags":["Projects"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"markdown":{"type":"string","minLength":1,"maxLength":20000},"timezone":{"type":"string","minLength":1,"default":"America/New_York"},"email_digest_enabled":{"type":"boolean"},"email_cc":{"type":"array","items":{"type":"string","format":"email"},"maxItems":10},"slack_digest_enabled":{"type":"boolean"},"slack_webhook_url":{"anyOf":[{"type":"string","minLength":1,"maxLength":512},{"type":"string","const":""},{"type":"null"}]},"send_test":{"type":"boolean"},"run_now":{"type":"boolean","default":true}},"required":["markdown"],"additionalProperties":false}}}},"summary":"Set up a project Radar","description":"Create an agent-managed RADAR.md and, by default, queue its first scan. timezone is optional and defaults to America/New_York when omitted. email_cc accepts up to 10 current organization-member email addresses."}},"/api/v1/projects/{projectId}/radar/run":{"post":{"responses":{"202":{"description":"Radar run queued"},"400":{"description":"Invalid RADAR.md or request body"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope, flag disabled, or plan limit"},"404":{"description":"Project not found"},"409":{"description":"Radar already exists"},"429":{"description":"Rate limited"}},"operationId":"postApiV1ProjectsByProjectIdRadarRun","tags":["Projects"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true}],"summary":"Run a Radar scan now","description":"Queue an additional scan, subject to the two-Scan-now-runs-per-Radar-local-day limit. Returns the same public run shape used by get Radar."}},"/api/v1/projects/{projectId}/radar/runs":{"get":{"responses":{"200":{"description":"Radar run history with funnel counts"},"400":{"description":"Invalid RADAR.md or request body"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope, flag disabled, or plan limit"},"404":{"description":"Project not found"},"409":{"description":"Radar already exists"},"429":{"description":"Rate limited"}},"operationId":"getApiV1ProjectsByProjectIdRadarRuns","tags":["Projects"],"parameters":[{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":50}},{"schema":{"type":"string"},"in":"path","name":"projectId","required":true}],"summary":"List project Radar runs"}},"/api/v1/projects/{projectId}/radar/runs/{runId}":{"get":{"responses":{"200":{"description":"Radar run and opportunities"},"400":{"description":"Invalid RADAR.md or request body"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope, flag disabled, or plan limit"},"404":{"description":"Project not found"},"409":{"description":"Radar already exists"},"429":{"description":"Rate limited"}},"operationId":"getApiV1ProjectsByProjectIdRadarRunsByRunId","tags":["Projects"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true},{"schema":{"type":"string"},"in":"path","name":"runId","required":true}],"summary":"Get a project Radar run"}},"/api/v1/projects/{projectId}/radar/opportunities/{opportunityId}/feedback":{"post":{"responses":{"200":{"description":"Feedback recorded"},"400":{"description":"Invalid RADAR.md or request body"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope, flag disabled, or plan limit"},"404":{"description":"Project not found"},"409":{"description":"Radar already exists"},"429":{"description":"Rate limited"}},"operationId":"postApiV1ProjectsByProjectIdRadarOpportunitiesByOpportunityIdFeedback","tags":["Projects"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"projectId","required":true},{"schema":{"type":"string"},"in":"path","name":"opportunityId","required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"verdict":{"type":"string","enum":["more_like_this","fewer_like_this","wrong_company","too_stale","never_pitch","not_our_expertise","undo"]},"note":{"type":"string","maxLength":500}},"required":["verdict"]}}}},"summary":"Record Radar opportunity feedback","description":"Records the verdict and echoes feedback.action, including undo, plus the resulting stored verdict so callers can confirm the write."}},"/api/v1/radar/today":{"get":{"responses":{"200":{"description":"Today's Radar across projects"},"400":{"description":"Invalid RADAR.md or request body"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient scope, flag disabled, or plan limit"},"404":{"description":"Project not found"},"409":{"description":"Radar already exists"},"429":{"description":"Rate limited"}},"operationId":"getApiV1RadarToday","tags":["Radar"],"parameters":[{"in":"query","name":"include_empty_projects","schema":{"type":"string","enum":["true","false"]}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}},{"in":"query","name":"cursor","schema":{"type":"string","minLength":1,"maxLength":2048}}],"summary":"Get today's organization Radar"}},"/api/v1/credits/balance":{"get":{"responses":{"200":{"description":"Credit balance"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Free-tier public API access is temporarily paused due to high traffic"}},"operationId":"getApiV1CreditsBalance","tags":["Medialyst API"],"parameters":[],"summary":"Get credit balance","description":"Return the authenticated organization's current credit balance. Use this before cost-incurring API calls."}},"/api/v1/journalist-moves":{"get":{"responses":{"200":{"description":"A bounded, de-duplicated journalist-move page","content":{"application/json":{"schema":{"type":"object","properties":{"moves":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^jm_[A-Za-z0-9_-]{24}$"},"name":{"type":"string"},"normalized_name":{"type":["string","null"]},"old_outlet":{"type":["string","null"]},"new_outlet":{"type":["string","null"]},"kind":{"type":"string","minLength":1,"maxLength":32},"role":{"type":["string","null"]},"beat":{"type":["string","null"]},"effective_date_text":{"type":["string","null"]},"match_state":{"type":"string","minLength":1,"maxLength":64},"journalist_identity_id":{"type":["string","null"]},"observed_at":{"type":"string","format":"date-time"},"published_at":{"type":["string","null"],"format":"date-time"},"sources":{"type":"array","items":{"type":"object","properties":{"source_id":{"type":"string","minLength":1,"maxLength":128},"source_url":{"type":["string","null"],"format":"uri","maxLength":2048},"evidence_quote":{"type":"string"},"observed_at":{"type":"string","format":"date-time"},"published_at":{"type":["string","null"],"format":"date-time"},"kind":{"type":"string","minLength":1,"maxLength":32},"match_state":{"type":"string","minLength":1,"maxLength":64},"extraction_lane":{"type":"string","minLength":1,"maxLength":64}},"required":["source_id","source_url","evidence_quote","observed_at","published_at","kind","match_state","extraction_lane"],"additionalProperties":false},"minItems":1}},"required":["id","name","normalized_name","old_outlet","new_outlet","kind","role","beat","effective_date_text","match_state","journalist_identity_id","observed_at","published_at","sources"],"additionalProperties":false}},"page":{"type":"object","properties":{"count":{"type":"integer","minimum":0,"maximum":250},"has_more":{"type":"boolean"},"next_cursor":{"type":"string","minLength":1,"maxLength":2048},"watermark":{"type":"string","format":"date-time"}},"required":["count","has_more","next_cursor","watermark"],"additionalProperties":false},"request_id":{"type":"string","minLength":1}},"required":["moves","page","request_id"],"additionalProperties":false}}}},"400":{"description":"Invalid timestamp, cursor, or limit"},"401":{"description":"Missing or invalid credential"},"403":{"description":"Credential's organization is not on an active Scale plan"},"429":{"description":"Rate limited or free-tier traffic temporarily shed"}},"operationId":"getApiV1Journalist-moves","tags":["Medialyst API"],"parameters":[{"in":"query","name":"since","schema":{"type":"string","format":"date-time"}},{"in":"query","name":"cursor","schema":{"type":"string","minLength":1,"maxLength":2048}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":250,"default":100}},{"in":"query","name":"kind","schema":{"type":"string","minLength":1,"maxLength":64}}],"summary":"Poll journalist outlet moves","description":"Return de-duplicated journalist outlet-move records observed after an exclusive timestamp or opaque cursor. `since` filters on when Medialyst observed each move — not the move's effective date — so a poller receives late-reported moves. Results are ordered by observed_at then stable id and collapse corroborating sources into one record. Each record carries `kind` (move, promotion, departure; filter with the optional `kind` query param) and `match_state`, which only says whether the name resolved to a Medialyst journalist record — not whether the move is real. Requires an active Scale-plan credential; calls are free and cost 0 credits."}},"/api/v1/news/search":{"post":{"responses":{"200":{"description":"News search response","content":{"application/json":{"schema":{"type":"object","properties":{"credits":{"type":"number","description":"Medialyst credits charged for this successful search page."},"items":{"type":"array","items":{"type":"object","properties":{"link":{"type":"string"},"url_status":{"type":"string","enum":["publisher","opaque"],"description":"Whether link is a publisher URL or an opaque wrapper; opaque means the link is a Google News redirect wrapper, not a publisher URL."},"metadata":{"type":"object","properties":{"publication_type":{"type":"string","nullable":true,"enum":["editorial","brand_content","newswire","government","syndication_platform","other",null]},"domain_authority":{"type":"number","nullable":true},"estimated_monthly_organic_traffic":{"type":"number","nullable":true,"description":"Estimated Similarweb monthly traffic rounded to two significant digits, or null if unavailable."}},"required":["publication_type","domain_authority","estimated_monthly_organic_traffic"],"additionalProperties":true}},"additionalProperties":true}},"results":{"type":"array","items":{"type":"object","properties":{"link":{"type":"string"},"url_status":{"type":"string","enum":["publisher","opaque"],"description":"Whether link is a publisher URL or an opaque wrapper; opaque means the link is a Google News redirect wrapper, not a publisher URL."},"metadata":{"type":"object","properties":{"publication_type":{"type":"string","nullable":true,"enum":["editorial","brand_content","newswire","government","syndication_platform","other",null]},"domain_authority":{"type":"number","nullable":true},"estimated_monthly_organic_traffic":{"type":"number","nullable":true,"description":"Estimated Similarweb monthly traffic rounded to two significant digits, or null if unavailable."}},"required":["publication_type","domain_authority","estimated_monthly_organic_traffic"],"additionalProperties":true}},"additionalProperties":true}},"news":{"type":"array","items":{"type":"object","properties":{"link":{"type":"string"},"url_status":{"type":"string","enum":["publisher","opaque"],"description":"Whether link is a publisher URL or an opaque wrapper; opaque means the link is a Google News redirect wrapper, not a publisher URL."},"metadata":{"type":"object","properties":{"publication_type":{"type":"string","nullable":true,"enum":["editorial","brand_content","newswire","government","syndication_platform","other",null]},"domain_authority":{"type":"number","nullable":true},"estimated_monthly_organic_traffic":{"type":"number","nullable":true,"description":"Estimated Similarweb monthly traffic rounded to two significant digits, or null if unavailable."}},"required":["publication_type","domain_authority","estimated_monthly_organic_traffic"],"additionalProperties":true}},"additionalProperties":true}},"articles":{"type":"array","items":{"type":"object","properties":{"link":{"type":"string"},"url_status":{"type":"string","enum":["publisher","opaque"],"description":"Whether link is a publisher URL or an opaque wrapper; opaque means the link is a Google News redirect wrapper, not a publisher URL."},"metadata":{"type":"object","properties":{"publication_type":{"type":"string","nullable":true,"enum":["editorial","brand_content","newswire","government","syndication_platform","other",null]},"domain_authority":{"type":"number","nullable":true},"estimated_monthly_organic_traffic":{"type":"number","nullable":true,"description":"Estimated Similarweb monthly traffic rounded to two significant digits, or null if unavailable."}},"required":["publication_type","domain_authority","estimated_monthly_organic_traffic"],"additionalProperties":true}},"additionalProperties":true}},"organic":{"type":"array","items":{"type":"object","properties":{"link":{"type":"string"},"url_status":{"type":"string","enum":["publisher","opaque"],"description":"Whether link is a publisher URL or an opaque wrapper; opaque means the link is a Google News redirect wrapper, not a publisher URL."},"metadata":{"type":"object","properties":{"publication_type":{"type":"string","nullable":true,"enum":["editorial","brand_content","newswire","government","syndication_platform","other",null]},"domain_authority":{"type":"number","nullable":true},"estimated_monthly_organic_traffic":{"type":"number","nullable":true,"description":"Estimated Similarweb monthly traffic rounded to two significant digits, or null if unavailable."}},"required":["publication_type","domain_authority","estimated_monthly_organic_traffic"],"additionalProperties":true}},"additionalProperties":true}}},"additionalProperties":true}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"402":{"description":"Payment Required"},"429":{"description":"Rate limited"},"500":{"description":"Internal configuration or billing error"}},"operationId":"postApiV1NewsSearch","tags":["Medialyst API"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"required":["q"],"properties":{"q":{"type":"string","description":"News search query."},"gl":{"type":"string","description":"Country code, such as us."},"hl":{"type":"string","description":"Interface language, such as en."},"page":{"type":"integer","minimum":1,"maximum":10,"description":"1-based page. Each page returns up to 10 results."},"tbs":{"type":"string","description":"Time filter, such as qdr:m."}}},"example":{"q":"\"AI infrastructure\" startup funding","gl":"us","page":2,"tbs":"qdr:m"}}}},"summary":"News search","description":"Search current news results for a query. Use page for deeper results; each page returns up to 10 items. Responses include news results plus Medialyst source classification metadata when available."}},"/api/v1/pr-calendar/query":{"post":{"responses":{"200":{"description":"PR calendar query response"},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Rate limited"}},"operationId":"postApiV1Pr-calendarQuery","tags":["Medialyst API"],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"q":{"type":"string","minLength":1,"maxLength":500},"industries":{"type":"array","items":{"type":"string","enum":["tech","fin","health","retail","media","food"]},"minItems":1,"maxItems":6},"types":{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":25},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":25},"audiences":{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":25},"country_codes":{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":25},"start_date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"end_date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"pitch_start_before":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"pitch_deadline_after":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"limit":{"type":"integer","minimum":1,"maximum":100,"default":25},"cursor":{"type":"string","minLength":1,"maxLength":500}},"additionalProperties":false}}}},"summary":"Query PR calendar","description":"Query Medialyst's PR calendar for source-backed awareness days, conferences, retail peaks, and cultural moments. Successful calls are free and cost 0 credits."}},"/api/v1/journalists/enrich":{"post":{"responses":{"200":{"description":"Completed idempotent replay","content":{"application/json":{"example":{"object":"journalist_enrichment_batch","status":"complete","journalists":[{"name":"Jane Doe","publicationMetrics":{"domain":"example.com","monthlyVisits":190000,"monthlyVisitsAsOf":"2026-09-01","domainRating":81,"aiVisibility":"High","aiCitationsGoogle":26012,"aiCitationsChatGpt":11869,"aiVisibilityAsOf":"2026-10-06T14:55:43.000Z","checkedAt":"2026-10-05T12:00:00.000Z"}}]}}}},"202":{"description":"Enrichment job accepted"},"400":{"description":"Invalid request, including a paid-placement article URL or PUBLICATION_NOT_FOUND when a publication-only reference cannot be mapped to a unique domain"},"401":{"description":"Unauthorized"},"402":{"description":"Payment Required"},"403":{"description":"Forbidden"},"409":{"description":"Idempotency conflict"},"429":{"description":"Too many active jobs (RATE_LIMITED), or the free plan's daily lookups are used (FREE_PLAN_DAILY_LIMIT)"},"500":{"description":"Failed to start enrichment job"}},"operationId":"postApiV1JournalistsEnrich","tags":["Medialyst API"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"example":{"from":[{"type":"journalist_reference","name":"Jane Doe","publication":"The Daily Example"}]}}}},"summary":"Enrich journalists from references or source articles","description":"Submit journalist_reference sources or editorial article_url sources and immediately receive a durable enrichment job. Paid, sponsored, partner, advertiser and brand-placement article URLs are rejected because they do not identify pitchable newsroom journalists. Each journalist_reference requires name plus at least one of publication, domain, or URL. Publication-only references are mapped to a canonical domain when the publication is known; otherwise the request returns PUBLICATION_NOT_FOUND and should be retried with domain supplied. Poll GET /v1/journalist-enrichment-jobs/:jobId until the job is complete or failed. Every resolved journalist includes publicationMetrics with monthlyVisits rounded to two significant digits, monthlyVisitsAsOf, domainRating, aiVisibility, aiCitationsGoogle, aiCitationsChatGpt, aiVisibilityAsOf, and checkedAt when publication data is available; unavailable values are null and do not cost extra credits. How often AI answers cite this outlet as a source: Highest, High, Some or Low. Based on citations in Google AI Overviews and ChatGPT (US). Include fit_context.pitch to also receive current journalist_research_v1 fit score, reasoning, and personalized angle results. Use this route for article authors and for many journalists at once; for one named journalist's email, use POST /v1/journalists/lookup. On the free plan, each source counts as one of the 3 daily lookups (UTC) shared with POST /v1/journalists/lookup; a request with more sources than remain today returns 429 FREE_PLAN_DAILY_LIMIT and spends nothing."}},"/api/v1/journalist-enrichment-jobs/{jobId}":{"get":{"responses":{"200":{"description":"Journalist enrichment job","content":{"application/json":{"example":{"id":"jej_123","object":"journalist_enrichment_job","status":"complete","result":{"object":"journalist_enrichment_batch","status":"complete","journalists":[{"name":"Jane Doe","publicationMetrics":{"domain":"example.com","monthlyVisits":190000,"monthlyVisitsAsOf":"2026-09-01","domainRating":81,"aiVisibility":"High","aiCitationsGoogle":26012,"aiCitationsChatGpt":11869,"aiVisibilityAsOf":"2026-10-06T14:55:43.000Z","checkedAt":"2026-10-05T12:00:00.000Z"}}]}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"}},"operationId":"getApiV1Journalist-enrichment-jobsByJobId","tags":["Medialyst API"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"jobId","required":true}],"summary":"Get journalist enrichment job status","description":"Returns progress and, when available, the enrichment result. Every resolved journalist in result.journalists includes publicationMetrics at no extra credit cost; Similarweb monthlyVisits is rounded to two significant digits and unavailable metric values are null. How often AI answers cite this outlet as a source: Highest, High, Some or Low. Based on citations in Google AI Overviews and ChatGPT (US)."}},"/api/v1/publications/lookup":{"get":{"responses":{"200":{"description":"Publication metadata"},"400":{"description":"Invalid URL or request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Rate limited"},"500":{"description":"Configuration error"},"502":{"description":"Provider lookup failed"}},"operationId":"getApiV1PublicationsLookup","tags":["Medialyst API"],"parameters":[{"in":"query","name":"url","schema":{"type":"string","minLength":1},"required":true},{"in":"query","name":"force_refresh","schema":{"anyOf":[{"type":"string","const":"true"},{"type":"string","const":"false"},{"type":"string","const":"1"},{"type":"string","const":"0"}]},"required":false}],"summary":"Lookup publication metadata","description":"Resolve a URL to Medialyst publication metadata. Cached rows are reused while fresh; stale or missing metrics are scraped through the publication metrics pipeline and written back. Similarweb monthly traffic is returned to two significant digits."}},"/api/v1/publications/lookup:batch":{"post":{"responses":{"200":{"description":"Publication metadata batch results"},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Rate limited"},"500":{"description":"Configuration error"},"502":{"description":"Provider lookup failed"}},"operationId":"postApiV1PublicationsLookup:batch","tags":["Medialyst API"],"parameters":[{"in":"query","name":"force_refresh","schema":{"anyOf":[{"type":"string","const":"true"},{"type":"string","const":"false"},{"type":"string","const":"1"},{"type":"string","const":"0"}]}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"urls":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"maxItems":25}},"required":["urls"],"additionalProperties":false}}}},"summary":"Batch lookup publication metadata","description":"Resolve up to 25 URLs to publication metadata. Results preserve input order and report per-URL errors so agents can continue after partial failures. Similarweb monthly traffic is returned to two significant digits."}},"/api/v1/journalists/lookup":{"post":{"responses":{"200":{"description":"found, checking, not_found or ambiguous, with the next step in `message`"},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"402":{"description":"Credits required to return the email"},"404":{"description":"Journalist not found"},"429":{"description":"Free-plan daily allowance used, daily live-check cap reached, or rate limited"}},"operationId":"postApiV1JournalistsLookup","tags":["Medialyst API"],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"q":{"type":"string","minLength":1,"maxLength":200},"find_live":{"type":"boolean"}},"required":["q"],"additionalProperties":false},{"type":"object","properties":{"journalist_id":{"type":"string","minLength":1,"maxLength":255}},"required":["journalist_id"],"additionalProperties":false}]}}}},"summary":"Look up a journalist's email","description":"One call from a name to a deliverable email. Send `q` (a name, ideally with the outlet, an email address or a profile URL) or a `journalist_id`. `status` is `found` (the deliverable `email`; 1 credit, and the same person is free for 30 days), `checking` (live checks are running: send the same body again after `retry_after_seconds`), `not_found` (no deliverable email; never guess one), or `ambiguous` (several people match: send one `candidates[].journalist_id`, or, when none is the person, the same `q` with `find_live: true` to find them live from the name and outlet). A free plan gets 3 lookups a day through the API and MCP, shared with POST /v1/journalists/enrich (`free_plan` shows what is left); a paid plan has no lookup allowance, only its daily live-check cap."}},"/api/v1/articles/lookup":{"get":{"responses":{"200":{"description":"Article lookup result"},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"402":{"description":"Payment Required"},"403":{"description":"Forbidden"},"429":{"description":"Rate limited"},"500":{"description":"Configuration error"},"502":{"description":"Article lookup failed"}},"operationId":"getApiV1ArticlesLookup","tags":["Medialyst API"],"parameters":[{"in":"query","name":"url","required":true,"description":"Absolute http(s) URL of the article to look up, e.g. https://example.com/story.","schema":{"type":"string","minLength":1}},{"in":"query","name":"include","required":false,"description":"Optional. Only `markdown` is supported; it adds the extracted article body as a `markdown` field. Author details are always included by default, so there is no `authors` include.","schema":{"type":"string","enum":["markdown"]}}],"summary":"Look up article metadata and optional Markdown"}},"/api/v1/articles/lookup:batch":{"post":{"responses":{"200":{"description":"Article lookup batch results"},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Rate limited"}},"operationId":"postApiV1ArticlesLookup:batch","tags":["Medialyst API"],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"urls":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"maxItems":10}},"required":["urls"],"additionalProperties":false}}}},"summary":"Look up multiple articles"}},"/api/v1/media-lists:create-async":{"post":{"responses":{"202":{"description":"Job accepted and durable media-list resource created","content":{"application/json":{"schema":{"type":"object","properties":{"media_list_id":{"type":["string","null"]},"workflow_id":{"type":["string","null"]},"media_list_url":{"type":["string","null"],"format":"uri"},"results_url":{"type":["string","null"],"format":"uri"},"job_id":{"type":"string"},"status":{"type":"string"},"target_list_size":{"type":"integer","exclusiveMinimum":0},"status_url":{"type":"string"},"project":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false}},"required":["media_list_id","workflow_id","media_list_url","results_url","job_id","status","target_list_size","status_url","project"]},"example":{"job_id":"job_01HT...","status":"pending","target_list_size":50,"status_url":"/api/v1/jobs/job_01HT...","media_list_id":"tbl_01HS...","workflow_id":"tbl_01HS...","media_list_url":"https://medialyst.ai/app/media-lists/tbl_01HS...","results_url":"https://medialyst.ai/api/v1/media-lists/tbl_01HS...?include_rows=true&row_detail=full&limit=100","project":{"id":"project_01HR...","name":"Acme launch"}}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"402":{"description":"Payment Required"},"403":{"description":"Insufficient scope"},"404":{"description":"Project not found"},"409":{"description":"Idempotency conflict"},"429":{"description":"Rate limited"}},"operationId":"postApiV1Media-lists:create-async","tags":["Medialyst API"],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"prompt":{"type":"string","minLength":1,"maxLength":2000},"topic":{"type":"string","minLength":1,"maxLength":2000},"target_list_size":{"type":"integer","minimum":1,"maximum":1000},"max_articles":{"type":"integer","minimum":1,"maximum":1000},"project_id":{"type":"string","minLength":1,"maxLength":255}}}}}},"summary":"Create a media list asynchronously","description":"Create the durable organization-scoped media-list table before dispatching background discovery. Omit project_id to use the Default project; supplying it requires projects:manage in addition to media_lists:manage, and the project must be active in the authenticated organization. Newly accepted jobs include an authenticated app URL that is safe to post to collaborators; it is not a public share link. A replay of a legacy table-less job may return null resource locators until the worker attaches its table. Poll status_url for progress and use results_url for the full first-party table data."}},"/api/v1/jobs/{jobId}":{"get":{"responses":{"200":{"description":"Job status and durable media-list links","content":{"application/json":{"schema":{"type":"object","properties":{"media_list_id":{"type":["string","null"]},"workflow_id":{"type":["string","null"]},"media_list_url":{"type":["string","null"],"format":"uri"},"results_url":{"type":["string","null"],"format":"uri"},"job_id":{"type":"string"},"status":{"type":"string"},"stage":{"type":"string","enum":["planning","enrichment","beat_sweep","done","failed","cancelled"]},"target_list_size":{"type":"integer","exclusiveMinimum":0},"created_at":{"type":["string","null"],"format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"},"progress":{"type":["object","null"],"properties":{"stage":{"type":"string"},"percent":{"type":"number"},"message":{"type":"string"}}},"result":{"type":["object","null"],"properties":{"workflow_id":{"type":"string"},"total_rows":{"type":"integer","minimum":0},"ready_rows":{"type":"integer","minimum":0},"failed_rows":{"type":"integer","minimum":0}},"required":["workflow_id","total_rows","ready_rows","failed_rows"]},"beat_sweep":{"type":["object","null"],"properties":{"status":{"type":"string"},"rows_added":{"type":"integer","minimum":0},"run_id":{"type":"string"},"reason":{"type":"string"}},"required":["status","rows_added"]},"budget":{"type":["object","null"],"properties":{"credits":{"type":"number","minimum":0},"spent":{"type":"number","minimum":0},"reserved":{"type":"number","minimum":0}},"required":["credits","spent","reserved"]},"error":{},"rows":{"type":"array","items":{"type":"object","additionalProperties":{}}},"page":{"type":"object","properties":{"next_cursor":{"type":["string","null"]}},"required":["next_cursor"]},"project":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false}},"required":["media_list_id","workflow_id","media_list_url","results_url","job_id","status","stage","target_list_size","created_at","updated_at","completed_at","progress","result","beat_sweep","budget"]}}}},"401":{"description":"Unauthorized"},"404":{"description":"Not found"}},"operationId":"getApiV1JobsByJobId","tags":["Medialyst API"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"jobId","required":true}],"summary":"Get media list job status","description":"Poll an asynchronous media-list job. Resource identifiers and the authenticated Medialyst app/results URLs remain stable from the initial pending response through processing and completion."}}},"components":{"schemas":{}}}