n8n-nodes-morning
v0.1.10
Published
n8n community node for Morning (Green Invoice) — Israeli accounting and invoicing API
Downloads
1,616
Maintainers
Readme
n8n-nodes-morning
n8n community node for Morning (formerly Green Invoice / חשבונית ירוקה) — the Israeli accounting and invoicing API.
Full coverage of the API surfaces a real workflow needs: documents, clients, suppliers, items, expenses, accounting classifications, business profile, and the hosted-checkout payment flow with auto-issued tax invoice + receipt. Includes a trigger node that receives Morning's notifyUrl webhooks.
Built against the live sandbox API (verified 2026-05-31).
What's included
Credentials: Morning (Green Invoice) API
- API Key ID + Secret + Environment (sandbox / production)
- Auto-fetches an OAuth access token via
POST /idp/v1/oauth/tokenon the auth host (api.morning.co/api.sandbox.morning.dev) usinggrant_type=client_credentials— refreshed on demand via n8n'sexpirabletoken field - Credential test pings
GET /businesses/me
Node: Morning (action)
| Resource | Operations | |---|---| | Document | Create · Get · Search · Email · Preview · Close · Open · Get Download Links · Get Info | | Client | Create · Get · Update · Search · Delete (tax ID validated client-side via mod-10) | | Supplier | Create · Get · Update · Search · Delete (tax ID validated client-side via mod-10) | | Item (Catalog) | Create · Get · Update · Search · Delete | | Expense | Create · Get · Search · Close · Open · Delete · Search Drafts · Get Statuses | | Payment | Create Payment Form · Search Links · Get Link · Search Saved Tokens · Charge Token · Create Token Link | | Transaction (עסקה) | Search · Get · Cancel · Refund · Count | | Recurring Payment (הוראת קבע) | Create · Get · Update · Delete · Search · Count · Get Jobs · Recharge · Unsuspend · Approve · Distribute · Search Failed Jobs · Export | | Retainer (ריטיינר) | Create · Get · Update · Delete · Search · Count · Get Jobs · Process Job | | Accounting | Get Classifications Map | | Business | Get Me · Get Numbering · Get Footer · Get Business Types |
65 operations across 11 resources.
Recurring Payment and Retainer wrap Morning's recurring-income features (הכנסות קבועות). A Recurring Payment (
/payments/recurrings) auto-charges a saved credit-card token on a schedule; a Retainer (/retainers) auto-issues a recurring document/payment-request to a client. These two endpoint families are not in Morning's official (Apiary) API reference — paths, verbs, bodies and enums were taken verbatim from Morning's own web-app client (and confirmed against a live recurring-payment response).Note the two resources use different
intervalencodings: Recurring Payment is1/2/3/12(months); Retainer is1m/2m/3m/6m/1y. Status filters are numeric: recurring5/10/20/30/50/60/70(pending/created/started/finished/canceled/suspended/expired), retainer1/2/3/10/20(created/started/finished/paused/deleted).The retainer create/update body is nested (from the web app's
buildData()):{ startDate, endDate, interval, doc: { …document fields, type }, data: { paymentTerms, description } }, built via dotted properties (doc.*,data.*).paymentTermsis a number (Immediate-1, or Net10/15/30/45/60/75/90/120);data.descriptionis a token (my= month-year,pmy= previous-month-year) or free text.Transaction (
/payments/transactions) reads and reverses the actual charge records behind payment forms, token charges and recurring runs — the counterpart to Payment, which creates the checkout links/forms/tokens. Search takes{ documentId, from, to, page, pageSize }(datesYYYY-MM-DD) and returns a pageditems[]withaggregations;Getadditionally returns the fullpaymentData(card number/expiry/token) that Search omits. Cancel (/cancel, no body) fully voids a still-cancellable charge; Refund (/refund, body{ amount }— omit for a full refund) returns money on a settled one. Both produce a new, linked reversal transaction (type: 25, negative amount,relatedTransactionId→ the original). Only rows withcancellable: truecan be voided. Paths/verbs were taken verbatim from Morning's own web-app payment service.Document → Create's "Enable Online Payment" attaches an online payment link (credit card / Bit / Apple Pay / Google Pay) directly to the document being created — the same one-call flow Morning's own web app uses when you toggle online payment on a Tax Invoice. It sends
paymentRequestData: { plugins: [{ id: pluginId, type: 12200, group }, ...], maxPayments }in the samePOST /documentsbody (not a separate/payments/formcall); the response carries apaymentRequestId, and once the customer pays, Morning auto-issues a linked receipt and closes the document. This is distinct from Payment → Create Payment Form, which always creates a brand-new combo document (320/400/405) from scratch rather than attaching a payment link to an existing/being-created document. Undocumented in Morning's Apiary reference — reverse-engineered from a live sandbox request captured from the web app's network traffic.
Trigger: Morning Trigger
- Receives the form-urlencoded webhook Morning POSTs to
notifyUrlafter a payment - Optional
?token=query-param verification (Morning does not sign webhooks, so this is the recommended guard) - Output: parsed (camelCase normalized) or raw
Built-in helpers (so you don't trip on Morning's gotchas)
- Israeli mod-10 (Luhn-variant) checksum validates
taxIdon client/supplier create before the request goes out. Rejects "123456789" with a clear error instead of waiting for Morning's Hebrew rejection. Test value000000018passes. - VAT math auto-compute (Payment → Create Payment Form): toggle "Auto-Compute Amount from Income" and the node calculates
amountfromincome[]×vatRateper the chosenvatType. No moreקיים חוסר התאמה בין סכום התקבולים לסכום התשלומיםerrors.
Install
Community Nodes panel (easiest — self-hosted n8n)
- In n8n: Settings → Community Nodes → Install.
- Enter the package name
n8n-nodes-morningand confirm. - The Morning and Morning Trigger nodes appear in the node panel.
Requires self-hosted n8n with community packages enabled (
N8N_COMMUNITY_PACKAGES_ENABLED=true, which is the default). n8n Cloud only lists verified community nodes in the panel.
npm (Docker / manual)
cd ~/.n8n/custom # mkdir -p ~/.n8n/custom first if it doesn't exist
npm install n8n-nodes-morning
# restart n8nFrom source (development)
git clone https://github.com/shirser121/n8n-nodes-morning.git
cd n8n-nodes-morning
npm install
npm run build
cd ~/.n8n/custom && npm install /absolute/path/to/n8n-nodes-morning
# restart n8nThe Morning node and Morning Trigger appear in the node panel.
Getting started
- Generate API keys at app.greeninvoice.co.il → המשתמש שלי → כלי מפתחים → API Keys (separate tabs for sandbox vs production).
- Create the credential in n8n: paste id, secret, pick environment. Hit "Test" — it should green-check against
/businesses/me. - Discover your
pluginId— drop aMorningnode, Resource: Document, Operation: Get Info, Type: 320. The response containspaymentPlugins[0].id— that's yourpluginIdfor any payment-form call. - Build the payment flow:
Morningnode → Resource: Payment → Op: Create Payment Form. Paste thepluginId. SetnotifyUrlto the URL of yourMorning Triggernode.Morning Triggernode → set a verification token, append?token=<value>to the URL you paste into notifyUrl.- Customer redirected to
response.urlfrom Create Payment Form → pays → Morning issues a tax invoice + receipt → webhook fires → workflow continues.
Gotchas built into the node (so you don't trip on them)
- Field naming is non-obvious. The node uses Morning's exact names:
income(notitems),paymentsingular (notpayments),emailsalways array (notemail),lang(notlanguage),remarks(notnotes). - VAT math —
amountmust matchincome[]based onvatType. The Auto-Compute toggle on payment-form does this for you. Manual math also works — the VAT-type dropdown spells out which mode means what. - Documents are immutable — there is no Update operation on Document, because Morning returns 405. To fix an issued doc, create a credit note (type 330) with
linkedDocumentIds, then issue a new one. - Clients/suppliers with docs/expenses can't be deleted — set
active: falseinstead (via Update). taxIdmust pass Israeli mod-10 checksum. The node validates this client-side. Test value:000000018.- Expense
documentType— use the supplier's invoice kind (305/320/400), NOT 10 (quote). The dropdown only shows valid options. - Expense
number— must be ≥5 numeric digits. "INV-001" and "1001" are both rejected. accountingClassification— pass the UUIDidfrom/accounting/classifications/map, not thecodeorkey. Use Resource: Accounting → Get Classifications Map to discover.- Rate limit ~3 req/s — n8n batches don't throttle by default. For high-volume workflows, add a Wait node.
Webhook security
Morning does not sign webhooks. Anything that knows your notifyUrl can forge a "paid" callback. Two guards:
- Use the trigger's "Verification Token (Query Param)" — append
?token=<long-random>to the URL you give Morning. The node rejects anything without a match. - The trigger output's
documentIdis Morning's UUID. After receiving, use aMorningaction node with Op: Get Document to fetch the canonical document — if the doc id is bogus, it 404s and you abort.
Notes for production
- The session token is cached for ~50 minutes (TTL is 60). The
expirable: trueflag on the credential's session token field tells n8n to re-callpreAuthenticationwhen needed. - The
notifyUrlcallback comes from AWS eu-west-1 (34.255.212.236observed) withUser-Agent: GreenInvoice/2.1. - Body is
application/x-www-form-urlencoded— n8n parses it automatically intoreq.body. - Be idempotent on
documentId— Morning may retry on 5xx/timeout. - Return 2xx fast (≤5s). Do heavy work async via a follow-on workflow.
Project structure
n8n-nodes-morning/
├── credentials/
│ └── MorningApi.credentials.ts JWT flow with auto-refresh
├── nodes/
│ ├── Morning/
│ │ ├── Morning.node.ts Declarative node wiring 8 resources
│ │ ├── helpers.ts mod-10 checksum + VAT math + preSend hooks
│ │ ├── morning.svg Icon (sunrise / "Morning" branding)
│ │ └── descriptions/ One file per resource
│ │ ├── DocumentDescription.ts
│ │ ├── ClientDescription.ts
│ │ ├── SupplierDescription.ts
│ │ ├── ItemDescription.ts
│ │ ├── ExpenseDescription.ts
│ │ ├── PaymentDescription.ts
│ │ ├── TransactionDescription.ts
│ │ ├── RecurringPaymentDescription.ts
│ │ ├── RetainerDescription.ts
│ │ ├── AccountingDescription.ts
│ │ └── index.ts
│ └── MorningTrigger/
│ ├── MorningTrigger.node.ts Webhook receiver for notifyUrl
│ └── morning.svg
├── package.json
├── tsconfig.json
└── README.mdDevelopment
npm install # dev deps: n8n-workflow, typescript, eslint
npm run typecheck # tsc --noEmit
npm run lint # eslint
npm run build # compile to dist/ + copy iconsdist/ is git-ignored and produced at build/publish time. Cutting a GitHub Release
publishes the package to npm automatically (see .github/workflows/publish.yml).
For the n8n verified community-node badge, switch linting over to
eslint-plugin-n8n-nodes-base (see the note in .eslintrc.js) and clear its
findings before submitting to n8n.
License
MIT — see LICENSE.
