Follow a Submission and Handle Outcomes
Every item in a submission carries two fields: status says where the item sits in the pipeline, and outcome says what it means for you, in particular who acts next. Branch your integration on outcome, and use closed_at, not status, to know a submission has settled. The complete reference lives in the Ingest API documentation.
Item outcomes
Each item reports its outcome alongside its status. The outcome tells you who acts next and what to do.
| Who acts next | What to do |
|---|---|---|
| Nobody yet | Keep polling. |
| Leasecake | Nothing. A reviewer, or the mapping step, has it. |
| You | Review and publish the draft lease. |
| You | Send the same file again; it may succeed. |
| You | Read the item's reason and act on it. |
| Nobody | Done. Its lease is published. |
| Nobody | Done. You withdrew the file. |
An item can also carry amendment_not_applied in warnings[] when a file typed amendment or addendum is linked to an existing lease as a supporting document and its outcome is matched or ready_for_review. The warning says the document's terms were not applied to the lease, so apply them to the lease in Leasecake. It is an additional warning, not a change to the item's status or outcome, and it clears if the file's type changes.
Know when a submission has settled
closed_at is set once every item in the submission reaches a terminal state. Poll until it is set, and treat it as the signal that the batch has settled, whatever its roll-up status says.
closed_at can change after it is set. Releasing a held item clears it, and confirming a held file is a lease sets it again once that item maps. So look back at a settled in_review submission now and then, and expect it to reopen as you answer held items.
Poll a submission
Poll GET /submissions/{submissionId} with backoff until closed_at is set, then pick out the items waiting on you: those whose outcome is ready_for_review, interrupted, or needs_attention.
async function settle(submissionId, token) {
let delay = 2_000;
while (true) {
const response = await fetch(`https://leasecake.cloud/ingest/v1/submissions/${submissionId}`, {
headers: { Authorization: `Bearer ${token}` },
});
const submission = await response.json();
if (submission.closed_at) {
return submission.items.filter((item) =>
['ready_for_review', 'interrupted', 'needs_attention'].includes(item.outcome),
);
}
await new Promise((resolve) => setTimeout(resolve, delay));
delay = Math.min(delay * 2, 60_000);
}
}To find every submission that needs you across your workspace, list submissions with awaiting_customer=true.
Answer an item held as unknown_document
An item held as unknown_document asks a question, such as what the file is or which lease it belongs to. Three endpoints answer it:
PATCH /submissions/{submissionId}/items/{itemId}: identify the file by answering the question it asked.POST /submissions/{submissionId}/items/{itemId}/hand-off: hand the file to Leasecake instead of answering.DELETE /submissions/{submissionId}/items/{itemId}: withdraw the file from the submission.
Read each item's removable flag and its outcome before acting, rather than deriving what is allowed from its status. Answering an item that is not waiting on your answer is refused with item-not-answerable.
Leases posted as JSON
A lease posted to POST /leases is recorded as a submission of its own, so you follow it exactly as you follow a file submission: through the Submission its response returns, with the same outcomes and the same polling.