{"id":14815,"plugin_id":"plugin_asdk_app_6aa7b09b97808191b0ced38534cd8782","kind":"skill","collection_source":null,"comparison_source":null,"observed_at":"2026-09-30T23:10:14.329Z","digest":"08dc95303cea86420abbbb34d77a499c50827babc8a73614e38e81347319afcc","against":null,"payload":{"description":"Create draft payables — new payment obligations to contractors — in Wingspan. Nothing is paid. Use for \"log a payment\", \"pay [name] $500 for [work]\", \"record these payments\", \"add these payments to the [engagement] engagement\", \"create payables\", \"log 12 hours at $85 for [name]\", \"bill this month's work\". Writes to the company's Wingspan account, so it always previews first.","included_files":[{"relative_path":"agents/openai.yaml","size_in_bytes":364}],"name":"creating-draft-payables","skill_md_contents":"---\nname: creating-draft-payables\ndescription: Create draft payables — new payment obligations to contractors — in Wingspan. Nothing is paid. Use for \"log a payment\", \"pay [name] $500 for [work]\", \"record these payments\", \"add these payments to the [engagement] engagement\", \"create payables\", \"log 12 hours at $85 for [name]\", \"bill this month's work\". Writes to the company's Wingspan account, so it always previews first.\n---\n\n# Creating draft payables\n\nThe shared rules for every call — ids, paging, previewing a write, what the\ntools cannot do — are in the `using-wingspan-tools` skill. Apply them here.\n\nA **payable** is one payment owed to one contractor — the row on the Payables\nscreen in the Wingspan app. An **engagement** is the named working arrangement\na payment is filed under. A **line item** is one priced line inside a payment.\n\n`create_payables` records payments against contractors' engagements. **It\nwrites to the company's account, and everything it creates is a draft.**\n\n## Always preview first\n\n1. Call `create_payables` with the rows and no `mode`. It defaults to\n   `mode: \"preview\"`, which writes nothing: it resolves each contractor and\n   engagement, checks every amount and date, totals it up, and reports exactly\n   what applying would do.\n2. Show that preview to the user in full — the per-row amounts, the total, the\n   engagement each payment lands on, every warning, and every row that cannot\n   be created.\n3. Wait for the user to say yes. An earlier \"log these payments\" is not consent\n   to write; the preview is the thing being consented to.\n4. Call again with `mode: \"apply\"`, a `requestId` you have not used before,\n   the matching preview's `confirmationToken` unchanged,\n   and the **same rows and the same `ref` values** you previewed.\n\nRetrying an apply with the same `requestId` and the same refs returns the\nresult of the original writes; nothing new is created. That is the only safe way\nto retry. A genuinely new attempt gets a new `requestId`.\n\n## Arguments\n\n| Argument | What it does |\n| --- | --- |\n| `payments` | The rows. At least one, at most 50 per call. |\n| `engagement` | An engagement, by name or id, for every row. Omit it and Wingspan uses each contractor's default engagement. A row's own `engagement` overrides it. |\n| `dueDate` | Default due date for every row, as `YYYY-MM-DD`. Required unless every row sets its own. |\n| `currency` | Currency for every row. Defaults to US dollars. |\n| `mode` | `preview` (the default, writes nothing) or `apply`. |\n| `confirmationToken` | Required with `apply`; copy it verbatim from the matching preview. If it expires or arguments change, preview again. |\n| `requestId` | Required with `apply`. An id of your own, up to 64 printable characters with no spaces. |\n| `accountId` | Write into one child account of an organization instead of the signed-in account. Only when the user names one; `who_am_i` lists them. |\n\nEach row in `payments`:\n\n| Field | What it does |\n| --- | --- |\n| `contractor` | **Required.** Their email, your external id for them, or their contractor id. |\n| `ref` | Your label for this row, echoed in the result. Up to 48 printable characters, no spaces and no colon. Defaults to `row-1`, `row-2` and so on. |\n| `referenceId` | Your own id for this payable, stored on it and searchable afterwards with `search_payables`' `referenceId` filter. One per payable — two cannot share one. |\n| `engagement` | The engagement for this row, by name or id. Overrides the top-level one. |\n| `amount` | A flat amount in dollars, for example `1200.50`. |\n| `quantity` | Units worked, for example hours. Goes with `unitCost`. |\n| `unitCost` | Amount per unit, in dollars. Goes with `quantity`. |\n| `unit` | What a unit is: `\"Hour\"`, `\"Unit\"`, or a label of your own. Defaults to `\"Unit\"`. |\n| `description` | What the work was. Shown as the line item's title. |\n| `detail` | Longer detail underneath the line item. |\n| `dueDate` | Due date for this row, as `YYYY-MM-DD`. Overrides the top-level one. |\n| `notes` | A note on the payment itself. The contractor can see it. |\n| `lineItems` | Several priced lines instead of the single-line fields above. |\n\nEach entry in `lineItems` takes `description`, `amount`, `quantity`,\n`unitCost`, `unit` and `detail`, with the same meanings.\n\n**`ref` and `referenceId` are different things.** `ref` is a label for this\ncall: it comes back in the result, it is what the retry key is built from, and\nit is gone once the call is done. `referenceId` is stored on the payable itself\nand is how the user finds that payment again later. A row can carry both, and\nthey do not have to match. Because no two payables can share a `referenceId`,\nreusing one is refused rather than attached to a second payment — which also\nmeans a genuine retry of an apply is safe, but re-sending the same\n`referenceId` under a *new* `requestId` is not.\n\n## Amounts\n\n**Amounts are in dollars.** `1200.50` is one thousand two hundred dollars and\nfifty cents. Never send cents.\n\n**Price a line one way or the other, never both.** Either a flat `amount`, or\n`quantity` together with `unitCost` — twelve hours at eighty-five dollars is\n`quantity: 12, unitCost: 85, unit: \"Hour\"`. Sending both is refused rather than\nguessed at, because it means the amount was expressed twice. A rate-priced line\nneeds both halves: `quantity` on its own, or `unitCost` on its own, is refused.\n\n**Use the single-line fields or `lineItems`, never both on one row.** Same\nreason.\n\n**Every amount has to be greater than zero.** A flat `amount` of zero, a\n`unitCost` of zero and a `quantity` of zero are each refused. A payment for\nnothing is never what the user meant.\n\n**A flat `amount` cannot be more precise than the currency.** US dollars are\npaid to two decimal places, so `10.999` is refused. Round the figure with the\nuser rather than picking one for them. A per-unit `unitCost` may be finer than\nthat — half a cent across a thousand units is a real way to price work — and\nWingspan does the multiplication.\n\n**A due date is required**, either on every row or once at the top level, and\nit is a calendar date: `YYYY-MM-DD`, no time and no timezone.\n\n## Engagements\n\nThe engagement decides which working arrangement the payment belongs to, and\n**it is fixed the moment the payment is created.** There is no way to move a\npayment to a different engagement afterwards — not from here, and not in the\napp. Getting it wrong means cancelling the payment and creating a new one. So\nwhen the engagement matters, confirm it with the user before applying.\n\nThe contractor must already be assigned to the engagement you name. If they are\nnot, the row fails and the preview lists which engagements they *are* assigned\nto. Assigning them is app work; the `onboarding-contractors` skill covers doing\nit for a new contractor.\n\nOmit the engagement entirely and Wingspan files the payment under the\ncontractor's default engagement. The preview says when that is happening, so\nshow it — a user who cares which engagement a payment lands on needs to see\nthat they did not name one.\n\n**This tool creates new payment obligations. It never moves existing ones.**\nA payable's engagement is fixed when it is created, and no tool here edits a\npayable. So \"add these payments to an engagement\" is ambiguous: if the user\nmeans payments that already exist in Wingspan, that cannot be done from here,\nand previewing a creation would propose duplicate obligations. Before calling\nthe tool, settle which one the user means. If they mean existing records,\ncheck with `search_payables` and say the engagement cannot be changed. If they\nmean new drafts, proceed. When the phrasing is \"log\", \"record\" or \"add\" a\npayment that has already been paid outside Wingspan, ask as well: a draft\npayable is a new obligation that Wingspan will expect to pay, not a record of\nmoney already sent.\n\n## Everything created here is a draft\n\nA payment created by this tool sits at draft. The contractor cannot see it and\nno payment is scheduled. Say this to the user every time, because \"log a\npayment\" often means \"and pay it\" in their head.\n\nWhat happens next: `open_payables` releases the draft, which is what shows it to\nthe contractor, and that is the one step available here. Approving it, and the\npayroll run that funds and pays it, happen in the Wingspan app. Paying is also\nprotected by an extra identity challenge, so it cannot be reached from here\nunder any circumstances.\n\n## The warning that matters most\n\n**Eligibility is checked when a payment is opened, not when it is created.** A\ndraft against a contractor with outstanding requirements is created happily\nand may then fail to open, if any of those requirements blocks eligibility.\nWhether a given outstanding requirement blocks depends on where it was\nattached, which these tools do not read, so say \"may not open\" rather than\n\"cannot open\". The preview flags the situation — \"onboarding requirements are\nincomplete, so this payable cannot be opened or paid until they are\" — and\nthat warning must reach the user, not be dropped as noise. Use\n`get_contractor` to say what is outstanding; the `finding-contractors` skill\ncovers reading it.\n\nThe preview also warns when a contractor's assignment to the named engagement\nis not active yet.\n\n## Batches\n\nFifty rows is the hard limit for one call; over that, the tool refuses and\nnames the limit. Each batch is its own attempt and needs its own `requestId`.\nOne bad row never stops the others — each row reports its own outcome by `ref`.\n\n## Where payments come from besides this tool\n\nAn invoice is not a payable. A payable is the payer's record of what it owes one\ncontractor. An invoice is a bill, and either side can raise one: a contractor\nbilling the company, or the company billing its own client. Payables can\noriginate from either kind of invoice as well as from payroll, and all of them\nshow up in `search_payables` alongside anything created here — the\n`checking-payments` skill covers reading them. A payable that came from an\ninvoice is owned by Wingspan and cannot be edited here.\n\n## Finish these in the Wingspan app\n\n- Approving a draft, scheduling it, cancelling it and paying it. Releasing it\n  so the contractor can see it is `open_payables`, not app work.\n- Starting a payroll run, and funding sources.\n- Moving a payment to a different engagement — impossible; cancel and recreate.\n- Invoices, payment splits, deductions and accounting integrations.\n- Creating engagements, and assigning a contractor to one.\n"},"changes":[],"summary":"First saved snapshot. No earlier version is available for comparison.","summary_kind":"deterministic","summary_metadata":{}}