{"openapi":"3.1.0","info":{"title":"Liney custom CRM contract","version":"v1","description":"The contract for connecting a CRM to Liney. The prose is https://www.liney.ai/developers/llms.txt."},"servers":[{"url":"https://www.liney.ai"}],"components":{"securitySchemes":{"key":{"type":"http","scheme":"bearer","description":"lk_test_… or lk_live_…"}},"schemas":{"schema-push":{"type":"object","properties":{"name":{"type":"string","description":"what the CRM is called; shown to reps in Liney"},"timezone":{"type":"string","description":"an IANA zone, e.g. America/Toronto"},"currency":{"type":"string","description":"a 3-letter code","pattern":"^[A-Z]{3}$"},"pipeline":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"}},"required":["id"],"additionalProperties":false},"fields":{"type":"object","properties":{"deals":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"the field key in your CRM; starts with a letter, then letters, digits, _ . -","pattern":"^[A-Za-z][A-Za-z0-9_.-]{0,99}$","maxLength":100},"label":{"type":"string","description":"what your users call it"},"type":{"type":"string","enum":["string","number","date","datetime","enum","bool"]},"options":{"type":"array","items":{"oneOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"}},"required":["value"],"additionalProperties":false}]},"description":"for enum fields: the values, with labels if they differ"},"role":{"type":"string","description":"which of the roles this field plays (one field per role)"},"readOnly":{"type":"boolean","description":"Liney shows it and never writes it"}},"required":["key","label","type"],"additionalProperties":false}},"contacts":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"the field key in your CRM; starts with a letter, then letters, digits, _ . -","pattern":"^[A-Za-z][A-Za-z0-9_.-]{0,99}$","maxLength":100},"label":{"type":"string","description":"what your users call it"},"type":{"type":"string","enum":["string","number","date","datetime","enum","bool"]},"options":{"type":"array","items":{"oneOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"}},"required":["value"],"additionalProperties":false}]},"description":"for enum fields: the values, with labels if they differ"},"role":{"type":"string","description":"which of the roles this field plays (one field per role)"},"readOnly":{"type":"boolean","description":"Liney shows it and never writes it"}},"required":["key","label","type"],"additionalProperties":false}},"companies":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"the field key in your CRM; starts with a letter, then letters, digits, _ . -","pattern":"^[A-Za-z][A-Za-z0-9_.-]{0,99}$","maxLength":100},"label":{"type":"string","description":"what your users call it"},"type":{"type":"string","enum":["string","number","date","datetime","enum","bool"]},"options":{"type":"array","items":{"oneOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"}},"required":["value"],"additionalProperties":false}]},"description":"for enum fields: the values, with labels if they differ"},"role":{"type":"string","description":"which of the roles this field plays (one field per role)"},"readOnly":{"type":"boolean","description":"Liney shows it and never writes it"}},"required":["key","label","type"],"additionalProperties":false}}},"required":["deals"],"additionalProperties":false},"stages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"order":{"type":"number"},"closed":{"type":"string","enum":["won","lost"],"description":"a closed stage; leave out for an open one"}},"required":["id","label","order"],"additionalProperties":false}},"owners":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"the user id in your CRM; the sign-in token names it as sub"},"name":{"type":"string"},"email":{"type":"string","description":"the address they sign in with; unique across owners","format":"email"}},"required":["id","name","email"],"additionalProperties":false}},"rules":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","description":"a deal field key"},"required":{"type":"boolean","description":"required on every deal"},"requiredAt":{"type":"array","items":{"type":"string"},"description":"required to enter these stage ids"},"requiredWhenClosed":{"type":"string","enum":["won","lost","both"]},"mustChange":{"type":"boolean","description":"the value must differ from what it holds, on every write"}},"required":["field"],"additionalProperties":false}},"capabilities":{"type":"object","properties":{"activities":{"type":"array","items":{"type":"string","enum":["note","call","task","meeting"]},"description":"what Liney may create on a record; default: note only"},"tasks":{"type":"boolean","description":"derived: true when activities includes task"},"companies":{"type":"string","enum":["full","readonly","none"]},"createCompany":{"type":"boolean"},"links":{"type":"string","enum":["full","create","none"],"description":"whether Liney may link a contact or company to a deal; full is read as create (Liney never removes a link)"},"merge":{"type":"boolean","description":"ignored: Liney never merges records on a custom CRM"},"deleteRestores":{"type":"boolean","description":"true when a remove in your CRM can be restored (a recycle bin); the checker keeps its destructive cases off a live key either way"}},"additionalProperties":false}},"required":["fields","stages","owners"],"additionalProperties":false,"description":"POST /api/crm/custom/v1/schema. Deal fields must give the roles name, stage, owner; the deal roles are name, stage, amount, closeDate, nextStep, owner, contact roles name, firstName, lastName, email, phone, title, company, company roles name, domain."},"records-push":{"type":"object","properties":{"mode":{"type":"string","enum":["upsert","replace"],"description":"upsert changes what you send (deleted: true is a tombstone); replace makes each mentioned owner's set exactly what you send"},"deals":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"owner":{"type":"string","description":"an owner id from the schema push"},"fields":{"type":"object","additionalProperties":{"type":["string","number","boolean","null"],"description":"a field value; dates as YYYY-MM-DD, datetimes as ISO 8601, enums as the option value"}},"deleted":{"type":"boolean"},"contacts":{"type":"array","items":{"type":"string"},"description":"contact ids linked to the deal"},"companies":{"type":"array","items":{"type":"string"},"description":"company ids linked to the deal"}},"required":["id","owner"],"additionalProperties":false}},"contacts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"owner":{"type":"string"},"fields":{"type":"object","additionalProperties":{"type":["string","number","boolean","null"],"description":"a field value; dates as YYYY-MM-DD, datetimes as ISO 8601, enums as the option value"}},"deleted":{"type":"boolean"},"companies":{"type":"array","items":{"type":"string"}}},"required":["id","owner"],"additionalProperties":false}},"companies":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"owner":{"type":"string"},"fields":{"type":"object","additionalProperties":{"type":["string","number","boolean","null"],"description":"a field value; dates as YYYY-MM-DD, datetimes as ISO 8601, enums as the option value"}},"deleted":{"type":"boolean"}},"required":["id","owner"],"additionalProperties":false}}},"required":["mode"],"additionalProperties":false,"description":"POST /api/crm/custom/v1/records. At most 5000 records per push."},"write-call":{"type":"object","properties":{"rep":{"type":"string","description":"the owner id of the rep whose line this is"},"deals":{"type":"object","description":"field values to set, by deal id","additionalProperties":{"type":"object","description":"field key → value","additionalProperties":{"type":"string"}}},"contacts":{"type":"object","description":"field values to set, by contact id","additionalProperties":{"type":"object","description":"field key → value","additionalProperties":{"type":"string"}}},"companies":{"type":"object","description":"field values to set, by company id","additionalProperties":{"type":"object","description":"field key → value","additionalProperties":{"type":"string"}}},"create":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"const":"deal"},"fields":{"type":"object","additionalProperties":{"type":"string"}},"companyId":{"type":["string","null"]}},"required":["type","fields"],"additionalProperties":false},{"type":"object","properties":{"type":{"const":"contact"},"dealId":{"type":["string","null"]},"name":{"type":"string"},"email":{"type":["string","null"]},"role":{"type":["string","null"],"description":"their job title"},"phone":{"type":["string","null"]},"properties":{"type":"object","additionalProperties":{"type":"string"}}},"required":["type","name"],"additionalProperties":false},{"type":"object","properties":{"type":{"const":"company"},"dealId":{"type":["string","null"]},"name":{"type":"string"},"ownerId":{"type":"string"},"domain":{"type":["string","null"]}},"required":["type","name"],"additionalProperties":false},{"type":"object","properties":{"type":{"const":"note"},"body":{"type":"string"},"target":{"type":"object","properties":{"objectType":{"enum":["deals","contacts","companies"],"description":"always plural"},"id":{"type":"string"}},"required":["objectType","id"],"additionalProperties":false},"also":{"type":"array","items":{"type":"object","properties":{"objectType":{"enum":["deals","contacts","companies"],"description":"always plural"},"id":{"type":"string"}},"required":["objectType","id"],"additionalProperties":false},"description":"records that should show it too; one you no longer have is skipped, not a refusal"},"ownerId":{"type":"string"}},"required":["type","body","target"],"additionalProperties":false},{"type":"object","properties":{"type":{"const":"call"},"body":{"type":"string"},"disposition":{"enum":["no_answer","connected","busy","left_voicemail","wrong_number"],"description":"how the call went"},"title":{"type":["string","null"]},"target":{"type":"object","properties":{"objectType":{"enum":["deals","contacts","companies"],"description":"always plural"},"id":{"type":"string"}},"required":["objectType","id"],"additionalProperties":false},"also":{"type":"array","items":{"type":"object","properties":{"objectType":{"enum":["deals","contacts","companies"],"description":"always plural"},"id":{"type":"string"}},"required":["objectType","id"],"additionalProperties":false},"description":"records that should show it too; one you no longer have is skipped, not a refusal"},"ownerId":{"type":"string"}},"required":["type","body","target"],"additionalProperties":false},{"type":"object","properties":{"type":{"const":"task"},"subject":{"type":"string"},"body":{"type":["string","null"]},"dueDate":{"type":"string","description":"YYYY-MM-DD"},"priority":{"enum":["NONE","LOW","MEDIUM","HIGH"]},"invite":{"type":["object","null"],"properties":{"title":{"type":"string"},"startTime":{"type":"string"},"endTime":{"type":["string","null"]}},"additionalProperties":false},"target":{"type":"object","properties":{"objectType":{"enum":["deals","contacts","companies"],"description":"always plural"},"id":{"type":"string"}},"required":["objectType","id"],"additionalProperties":false},"also":{"type":"array","items":{"type":"object","properties":{"objectType":{"enum":["deals","contacts","companies"],"description":"always plural"},"id":{"type":"string"}},"required":["objectType","id"],"additionalProperties":false}},"ownerId":{"type":"string"}},"required":["type","subject","dueDate","target"],"additionalProperties":false},{"type":"object","properties":{"type":{"const":"meeting"},"title":{"type":"string"},"startTime":{"type":"string","description":"ISO 8601"},"endTime":{"type":["string","null"]},"body":{"type":["string","null"]},"target":{"type":"object","properties":{"objectType":{"enum":["deals","contacts","companies"],"description":"always plural"},"id":{"type":"string"}},"required":["objectType","id"],"additionalProperties":false},"also":{"type":"array","items":{"type":"object","properties":{"objectType":{"enum":["deals","contacts","companies"],"description":"always plural"},"id":{"type":"string"}},"required":["objectType","id"],"additionalProperties":false}},"ownerId":{"type":"string"}},"required":["type","title","startTime","target"],"additionalProperties":false}]},"description":"things to make, in order; the reply names each new id"},"links":{"type":"array","items":{"type":"object","properties":{"from":{"type":"object","properties":{"objectType":{"enum":["deals","contacts","companies"]},"id":{"type":"string"}},"additionalProperties":false},"to":{"type":"object","properties":{"objectType":{"enum":["deals","contacts","companies"]},"id":{"type":"string"}},"additionalProperties":false}},"required":["from","to"],"additionalProperties":false},"description":"links to add; never removed by Liney"},"tasks":{"type":"object","properties":{"complete":{"type":"array","items":{"type":"string"},"description":"task ids to mark done"}},"required":["complete"],"additionalProperties":false}},"required":["rep"],"additionalProperties":false,"description":"POST <your endpoint>/liney/write. Every key besides rep is optional; a call carries the parts a line item needs and nothing else."},"undo-call":{"type":"object","properties":{"rep":{"type":"string"},"expect":{"type":"object","description":"what Liney last read for each field it is about to restore: compare before you write","propertyNames":{"enum":["deals","contacts","companies"]},"additionalProperties":{"type":"object","description":"record id → field values","additionalProperties":{"type":"object","additionalProperties":{"type":["string","null"]}}}},"restore":{"type":"object","description":"the values to put back; null clears the field","propertyNames":{"enum":["deals","contacts","companies"]},"additionalProperties":{"type":"object","description":"record id → field values","additionalProperties":{"type":"object","additionalProperties":{"type":["string","null"]}}}},"remove":{"type":"array","items":{"type":"object","properties":{"type":{"enum":["deal","contact","company","note","call","task","meeting","task_done","link"]},"id":{"type":"string","description":"an id your CRM gave Liney in a write reply"},"previous":{"type":"string","description":"for task_done: the status to put back"}},"required":["type","id"],"additionalProperties":false},"description":"things Liney made in this line, to remove; task_done reopens a task; a second remove of something already gone is not an error"}},"required":["rep"],"additionalProperties":false,"description":"POST <your endpoint>/liney/undo. Compare-and-set: every field in expect must equal what the record holds, or reply conflict and change nothing."},"reply":{"description":"The reply to a write, an undo, or an outbox answer.","oneOf":[{"type":"object","properties":{"ok":{"const":true},"previous":{"type":"object","description":"for every field the call set: the value it held before, by object type then id","propertyNames":{"enum":["deals","contacts","companies"]},"additionalProperties":{"type":"object","description":"record id → field values","additionalProperties":{"type":"object","additionalProperties":{"type":["string","null"]}}}},"created":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string"}},"required":["type","id"],"additionalProperties":false},"description":"one entry per item in create, in order"},"dryRun":{"type":"boolean"}},"required":["ok"],"additionalProperties":false},{"type":"object","properties":{"ok":{"const":false},"error":{"type":"object","properties":{"code":{"type":"string","enum":["required_field","invalid_value","not_found","conflict","rate_limited"]},"message":{"type":"string","description":"shown to the rep, so say what to do"},"field":{"type":"string","description":"the field key the refusal is about, when there is one"}},"required":["code","message"],"additionalProperties":false}},"required":["ok","error"],"additionalProperties":false}]},"outbox-item":{"type":"object","properties":{"id":{"type":"string"},"kind":{"enum":["write","undo"]},"idempotencyKey":{"type":"string"},"dryRun":{"type":"boolean"},"lease":{"type":"string","description":"send it back as X-Liney-Lease"},"leasedUntil":{"type":"string","description":"ISO 8601"},"body":{"type":"object","description":"the write-call or undo-call"}},"required":["id","kind","idempotencyKey","dryRun","lease","leasedUntil","body"],"additionalProperties":false,"description":"GET /api/crm/custom/v1/outbox: one leased call, or 204 when there is none within the hold."},"sso-token":{"type":"object","properties":{"sub":{"type":"string","description":"the owner id from your schema push"},"email":{"type":"string","description":"informational; who signs in is the pushed owner's email"},"name":{"type":"string"},"slug":{"type":"string","description":"the team's address on Liney"},"nonce":{"type":"string","description":"unique per token"},"exp":{"type":"integer","description":"unix seconds; at most 300 s ahead"}},"required":["sub","email","slug","nonce","exp"],"additionalProperties":false,"description":"The JSON inside a sign-in token: base64url(json) + \".\" + base64url(HMAC-SHA256(secret, base64url(json)))."},"line-request":{"type":"object","properties":{"text":{"type":"string","description":"the rep's line, their own words"},"dealId":{"type":"string","description":"the deal the line is about, when your page knows it (one of the rep's pushed deals); else Liney finds it"},"today":{"type":"string","description":"YYYY-MM-DD in the rep's day; default: today in the connection's timezone"}},"required":["text"],"additionalProperties":false,"description":"POST /api/crm/custom/v1/lines, with X-Liney-Rep: <owner id> and your key."},"line-question":{"type":"object","properties":{"property":{"type":"string","description":"a field key, or a pseudo key such as __date"},"why":{"type":"string","description":"shown to the rep"},"options":{"type":"array","items":{"type":"string"}},"blocking":{"type":"boolean","description":"true: the write waits for an answer"},"record":{"type":"object","properties":{"objectType":{"enum":["contacts","companies"]},"id":{"type":"string"},"name":{"type":"string"}},"required":["objectType","id","name"],"additionalProperties":false}},"required":["property","why","options","blocking"],"additionalProperties":false},"line-reply":{"type":"object","properties":{"ok":{"const":true},"lineId":{"type":"string"},"status":{"type":"string","description":"ready"},"deal":{"type":["object","null"],"properties":{"id":{"type":"string"},"name":{"type":["string","null"]}},"required":["id"],"additionalProperties":false},"proposal":{"type":"object","description":"the field changes (fields[]: property, value, previous, required), engagements[] to make, contacts[] and newCompanies[] to create, recordUpdates[], links[], createDeal (a deal to make, or null), match.alternatives and existingDeals, recordChoices[], taskChoices[]; no reasons, no scores","additionalProperties":true},"questions":{"type":"array","items":{"$ref":"#/components/schemas/line-question"}}},"required":["ok","lineId","status","deal","proposal","questions"],"additionalProperties":false},"answer-request":{"type":"object","properties":{"answers":{"type":"object","additionalProperties":{"type":"string"},"description":"the rep's answers, keyed by the question's property"},"dropStage":{"type":"boolean","description":"keep the stage as it is and write the rest"},"dealId":{"type":["string","null"],"description":"a deal from the proposal (its match, alternatives or existingDeals) or another of the rep's"},"createDeal":{"type":["object","null"],"properties":{"name":{"type":"string"}},"required":["name"],"additionalProperties":false,"description":"make the deal the proposal offered"}},"additionalProperties":false,"description":"POST /api/crm/custom/v1/lines/{id}/answer"},"write-request":{"type":"object","properties":{"dryRun":{"type":"boolean","description":"send the calls with X-Liney-Dry-Run and record nothing (or send the header)"}},"additionalProperties":false,"description":"POST /api/crm/custom/v1/lines/{id}/write; the body may be left out"},"headless-line":{"type":"object","properties":{"id":{"type":"string"},"status":{"enum":["draft","asking","ready","writing","written","queued","rejected","reverted"]},"text":{"type":"string"},"deal":{"type":["object","null"],"properties":{"id":{"type":"string"},"name":{"type":["string","null"]}},"required":["id"],"additionalProperties":false},"written":{"type":["object","null"],"additionalProperties":{"type":"string"}},"previous":{"type":["object","null"],"additionalProperties":{"type":["string","null"]}},"engagements":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string"}},"required":["type","id"],"additionalProperties":false}},"records":{"type":["array","null"],"items":{"type":"object","additionalProperties":true}},"error":{"type":["object","null"],"properties":{"message":{"type":"string"},"code":{"type":"string"},"partial":{"type":"boolean"},"missing":{"type":"array","items":{"type":"string"}}},"required":["message"],"additionalProperties":false},"clientDay":{"type":"string"},"revertedAt":{"type":["string","null"]}},"required":["id","status","text","deal","written","previous","engagements","error","clientDay"],"additionalProperties":false},"write-reply":{"type":"object","properties":{"ok":{"const":true},"lineId":{"type":"string"},"status":{"enum":["written","asking","rejected","queued","reconnect","allowance","writing"]},"line":{"$ref":"#/components/schemas/headless-line"},"questions":{"type":"array","items":{"$ref":"#/components/schemas/line-question"},"description":"asking: answer these and write again"},"learned":{"type":"array","items":{"type":"string"},"description":"asking: fields your handler just refused as required_field, now rules"},"message":{"type":"string","description":"rejected: shown to the rep"},"cause":{"type":"string","description":"queued: relay, network, 429, 5xx or paused; asking: blocking (a blocking question has no answer; nothing was sent), changed (a field moved under the line) or admin (a required field is empty)"},"canKeepStage":{"type":"boolean","description":"rejected: the line can be written with dropStage"},"partial":{"type":"string","description":"written: what did not save and will be retried"},"dryRun":{"type":"boolean"},"calls":{"type":"array","items":{"type":"object","properties":{"kind":{"enum":["write","undo"]},"idempotencyKey":{"type":"string"},"delivery":{"enum":["push","pull"]},"dryRun":{"type":"boolean"},"ok":{"type":"boolean"},"status":{"type":["integer","null"]},"error":{"type":["string","null"]},"ms":{"type":"integer"}},"required":["kind","idempotencyKey","delivery","dryRun","ok","ms"],"additionalProperties":false}}},"required":["ok","lineId","status","line","dryRun","calls"],"additionalProperties":false},"undo-request":{"type":"object","properties":{"force":{"type":"boolean","description":"write over a field a person changed since the line"}},"additionalProperties":false,"description":"POST /api/crm/custom/v1/lines/{id}/undo; the body may be left out"},"undo-reply":{"type":"object","properties":{"ok":{"const":true},"lineId":{"type":"string"},"status":{"enum":["reverted","conflict","not_undoable"]},"line":{"$ref":"#/components/schemas/headless-line"},"failed":{"type":"array","items":{"type":"string"},"description":"reverted: what your handler refused as conflict, in the rep's words"},"conflicts":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"conflict: property, current, written, previous per field"},"cause":{"type":"string","description":"not_undoable: why not, in the rep's words"},"calls":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["ok","lineId","status","calls"],"additionalProperties":false},"error":{"type":"object","properties":{"ok":{"const":false},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"hint":{"type":"string","description":"what to do next"},"docs":{"type":"string","description":"the anchor in llms.txt","format":"uri"}},"required":["code","message","hint","docs"],"additionalProperties":false}},"required":["ok","error"],"additionalProperties":false,"description":"Every refusal from a Liney API route."},"check-request":{"type":"object","properties":{"case":{"type":"string","description":"a case id from GET …/check; omit to run every case allowed for the key, one request per case is quicker"},"url":{"type":"string","description":"with the test key: the endpoint to check, push mode; sets the test target (the live target is set on the connection card only)"},"delivery":{"enum":["push","pull"],"description":"with the test key: pull sets the test target to pull mode"}},"additionalProperties":false,"description":"POST /api/crm/custom/v1/check"},"check-result":{"type":"object","properties":{"key":{"enum":["test","live"]},"target":{"type":"object","properties":{"delivery":{"enum":["push","pull"]},"url":{"type":["string","null"]}},"additionalProperties":false},"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"enum":["pass","fail","skip"]},"detail":{"type":"string"},"hint":{"type":"string"},"docs":{"type":"string"},"mutating":{"type":"boolean"},"ms":{"type":"integer"}},"required":["id","name","status","detail","mutating","ms"],"additionalProperties":false}},"passed":{"type":"integer"},"failed":{"type":"integer"},"skipped":{"type":"integer"},"green":{"type":"boolean","description":"every case allowed for this key passed or skipped for a stated reason"}},"required":["key","target","results","passed","failed","skipped","green"],"additionalProperties":false}}},"paths":{"/api/crm/custom/v1/schema":{"post":{"summary":"Push schema","security":[{"key":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/schema-push"}}}},"responses":{"200":{"description":"accepted"},"400":{"description":"refused; see error.hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}},"401":{"description":"no valid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}},"403":{"description":"test key after go-live","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}}}}},"/api/crm/custom/v1/records":{"post":{"summary":"Push records","security":[{"key":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/records-push"}}}},"responses":{"200":{"description":"accepted"},"400":{"description":"refused; see error.hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}},"401":{"description":"no valid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}},"413":{"description":"too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}}}}},"/api/crm/custom/v1/outbox":{"get":{"summary":"Pull mode: the next call for this key's target","security":[{"key":[]}],"responses":{"200":{"description":"a leased call","content":{"application/json":{"schema":{"$ref":"#/components/schemas/outbox-item"}}}},"204":{"description":"nothing within the hold"},"401":{"description":"no valid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}}}}},"/api/crm/custom/v1/outbox/{id}":{"post":{"summary":"Pull mode: answer a leased call","security":[{"key":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-Liney-Lease","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/reply"}}}},"responses":{"200":{"description":"answered"},"400":{"description":"the reply is outside the contract","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}},"404":{"description":"no such item","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}},"409":{"description":"lease expired or already answered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}}}}},"/api/crm/custom/v1/lines":{"post":{"summary":"Headless: read a line as a rep (one model call)","security":[{"key":[]}],"parameters":[{"name":"X-Liney-Rep","in":"header","required":true,"schema":{"type":"string"},"description":"the rep whose line it is: an owner id from your schema push"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/line-request"}}}},"responses":{"200":{"description":"the proposal and its questions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/line-reply"}}}},"400":{"description":"refused; see error.hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}},"401":{"description":"no valid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}},"404":{"description":"unknown rep or deal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}},"409":{"description":"no target, no schema, or the live key before go-live","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}},"429":{"description":"rate limited; Retry-After says when","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}}}}},"/api/crm/custom/v1/lines/{id}":{"get":{"summary":"Headless: the line as it stands, with the blocking questions still open","security":[{"key":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"the lineId POST /lines answered"},{"name":"X-Liney-Rep","in":"header","required":true,"schema":{"type":"string"},"description":"the rep whose line it is: an owner id from your schema push"}],"responses":{"200":{"description":"the line","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"lineId":{"type":"string"},"status":{"type":"string"},"line":{"$ref":"#/components/schemas/headless-line"},"questions":{"type":"array","items":{"$ref":"#/components/schemas/line-question"}}},"additionalProperties":false}}}},"404":{"description":"no such line for that rep","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}}}}},"/api/crm/custom/v1/lines/{id}/answer":{"post":{"summary":"Headless: the rep's answers","security":[{"key":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"the lineId POST /lines answered"},{"name":"X-Liney-Rep","in":"header","required":true,"schema":{"type":"string"},"description":"the rep whose line it is: an owner id from your schema push"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/answer-request"}}}},"responses":{"200":{"description":"the questions still open","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"lineId":{"type":"string"},"status":{"type":"string"},"deal":{"type":["object","null"],"properties":{"id":{"type":"string"},"name":{"type":["string","null"]}},"additionalProperties":false},"questions":{"type":"array","items":{"$ref":"#/components/schemas/line-question"}}},"additionalProperties":false}}}},"404":{"description":"no such line for that rep","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}},"409":{"description":"the line is already written","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}}}}},"/api/crm/custom/v1/lines/{id}/write":{"post":{"summary":"Headless: write the line to the key's target","security":[{"key":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"the lineId POST /lines answered"},{"name":"X-Liney-Rep","in":"header","required":true,"schema":{"type":"string"},"description":"the rep whose line it is: an owner id from your schema push"},{"name":"X-Liney-Dry-Run","in":"header","required":false,"schema":{"type":"string","enum":["1"]}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/write-request"}}}},"responses":{"200":{"description":"the outcome","content":{"application/json":{"schema":{"$ref":"#/components/schemas/write-reply"}}}},"404":{"description":"no such line for that rep","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}}}}},"/api/crm/custom/v1/lines/{id}/undo":{"post":{"summary":"Headless: undo a written line","security":[{"key":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"the lineId POST /lines answered"},{"name":"X-Liney-Rep","in":"header","required":true,"schema":{"type":"string"},"description":"the rep whose line it is: an owner id from your schema push"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/undo-request"}}}},"responses":{"200":{"description":"the outcome","content":{"application/json":{"schema":{"$ref":"#/components/schemas/undo-reply"}}}},"404":{"description":"no such line for that rep","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}}}}},"/api/crm/custom/v1/check":{"get":{"summary":"The checker cases this key may run","security":[{"key":[]}],"responses":{"200":{"description":"the list","content":{"application/json":{"schema":{"type":"object","properties":{"key":{"enum":["test","live"]},"target":{"type":"object","properties":{"delivery":{"enum":["push","pull"]},"url":{"type":["string","null"]}},"additionalProperties":false},"cases":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"mutating":{"type":"boolean"},"docs":{"type":"string"}},"additionalProperties":false}}},"additionalProperties":false}}}},"401":{"description":"no valid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}}}},"post":{"summary":"Run one checker case (or every allowed case)","security":[{"key":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/check-request"}}}},"responses":{"200":{"description":"the results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/check-result"}}}},"400":{"description":"refused; see error.hint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}},"401":{"description":"no valid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/error"}}}}}}}},"webhooks":{"write":{"post":{"summary":"Liney → your endpoint: POST <endpoint>/liney/write","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/write-call"}}}},"responses":{"200":{"description":"the reply","content":{"application/json":{"schema":{"$ref":"#/components/schemas/reply"}}}},"401":{"description":"bad signature"}}}},"undo":{"post":{"summary":"Liney → your endpoint: POST <endpoint>/liney/undo","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/undo-call"}}}},"responses":{"200":{"description":"the reply","content":{"application/json":{"schema":{"$ref":"#/components/schemas/reply"}}}},"401":{"description":"bad signature"}}}}}}