Skip to main content

morning-cli banner

PyPI version Python versions CI status License Downloads

morning API v2  |  OAuth 2.0 auth  |  Interactive REPL  |  Onboarding wizard  |  JSON envelopes for AI agents  |  Hebrew error messages

Built by JangoAI using the cli-anything methodology  |  README בעברית


Why this exists

I'm Maor, a solo developer running JangoAI — a small AI automation studio in Israel. I use morning's API daily for my own business and my clients', and I got tired of writing the same httpx + JWT boilerplate in every project. So I built a proper CLI around it.

This started as a personal tool, but there's no reason to keep it private — if you work with morning's API, you'll save time with this. I'm sharing it with the Israeli dev community because I think we deserve better tooling for our local platforms. If it helps you, I'd love to hear about it.

v0.2.0 — API v2 ready. morning rewrote their developer docs at developers.morning.co (OpenAPI 2.0.0): OAuth 2.0 token endpoint on dedicated IDP hosts, a new presigned-S3 expense upload flow, Basic-auth partners endpoints, and reference data staying on the shared cache host. This release tracks all of it, with automatic fallback to the legacy token endpoint where the new IDP isn't deployed. See the CHANGELOG.


Install

pip install morning-cli

Get started in 30 seconds

# 1. Run the interactive wizard — connects your morning account
morning-cli auth init

# 2. Start the REPL
morning-cli

# 3. Or use one-shot commands
morning-cli --json auth whoami
morning-cli --json document types --lang he
morning-cli --json client search
What does auth init look like?
  ╭──────────────────────────────────────────────────╮
  │       morning-cli                                │
  │       setup wizard                               │
  │                                                  │
  │       Connect your morning account.              │
  │       You'll be up and running in under a minute.│
  ╰──────────────────────────────────────────────────╯

  >>  Step 1/4  Choose environment
  ╭──────────────────────────────────────────────────╮
  │ Where do you want to connect?                    │
  │   [1]  sandbox      Safe testing, no real money  │
  │   [2]  production   Live business data           │
  ╰──────────────────────────────────────────────────╯
  Enter 1 or 2 [1]:

  OK  Step 1/4  Choose environment
  >>  Step 2/4  Get your API keys
  ╭─ Open in browser ────────────────────────────────╮
  │ https://app.greeninvoice.co.il/settings/developers/api
  │ Settings > Advanced > Developers > Create API Key│
  ╰──────────────────────────────────────────────────╯

  >>  Step 3/4  Enter credentials
    API Key ID:     xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    API Key Secret: (hidden as you type)

  >>  Step 4/4  Verify connection
  Connecting to morning API...

  ╭─ All set ────────────────────────────────────────╮
  │  Connected successfully!                         │
  │  Business   Your Business Name                   │
  │  Env        SANDBOX                              │
  │  Saved to   ~/.greeninvoice/credentials.json     │
  ╰──────────────────────────────────────────────────╯

Commands

Group Endpoints Highlights
authlocalinit (wizard), login, logout, whoami, refresh
sessionlocalshow, reset, history
business10 (legacy)list, current, get, update, numbering, footer, types, file-upload — removed from the v2 docs, still served
client8add, get, update, delete, search, assoc, merge, balance
supplier6add, get, update, delete, search, merge
item5add, get, update, delete, search
document13create, preview, get, search, close, open, download, types, statuses
expense13CRUD + open/close + upload (presigned-S3 flow) + drafts-search/draft-delete
payment3form, tokens-search, charge
partner3users, connect, disconnect (HTTP Basic)
tools4occupations, countries, cities, currencies — shared cache host, no auth

Usage examples

Create a proforma invoice (חשבון עסקה)

cat > /tmp/proforma.json <<'JSON'
{
  "description": "ריטיינר חודשי",
  "type": 300,
  "lang": "he",
  "currency": "ILS",
  "vatType": 0,
  "client": {"name": "Acme Ltd", "emails": ["ap@acme.com"], "country": "IL"},
  "income": [
    {"description": "שירותי ייעוץ", "quantity": 10, "price": 300, "currency": "ILS", "vatType": 0}
  ]
}
JSON
morning-cli --json document create --file /tmp/proforma.json

Search recent clients

morning-cli --json client search --data '{"page":1,"pageSize":10}'

Get PDF download link for a document

morning-cli --json document download <document_id>

Upload an expense receipt (API v2 presigned-S3 flow)

morning-cli --json expense upload receipt.pdf          # new expense draft
morning-cli --json expense upload receipt.pdf --id <expense_id>   # attach to expense
morning-cli --json expense drafts-search               # parsed draft appears here

JSON output for AI agents

Every --json command returns a consistent envelope:

{"ok": true, "op": "document.create", "data": {"id": "...", "number": 12345}}

Errors include the morning errorCode and Hebrew errorMessage:

{"ok": false, "op": "document.create", "error": {"code": 1110, "message": "מחיר לא תקין.", "http_status": 400}}
Exit code Meaning
0 Success
1 Unexpected internal error / aborted confirmation
2 Usage error, local config error (e.g. missing credentials), or API error (4xx)
3 Server error (5xx) / network failure

Success envelopes go to stdout; error envelopes go to stderr (agents: capture both streams).

Common morning API error codes
Code Meaning
401 Token expired (CLI auto-refreshes)
1003 No active business in the account
1006 Subscription expired
1007 Missing permission
1012 Feature requires a higher plan
1110 Invalid price in a line item
2002 Wrong email or password
2102 Can't add more businesses on this plan
2403 Document type not supported for this business type

Environment variables

Variable Purpose Default
MORNING_API_KEY_ID API key ID
MORNING_API_KEY_SECRET API key secret
MORNING_ENV sandbox or production sandbox
MORNING_BASE_URL Override the core REST base URL auto
MORNING_GATEWAY_URL Override the OAuth IDP + file-upload hosts (proxies/custom deploys) auto
MORNING_AUTH_MODE auto (OAuth with legacy fallback), oauth (no fallback), legacy (skip IDP) auto

How auth works (v0.2.0+): the CLI obtains a 1-hour access token via OAuth 2.0 client_credentials from the morning IDP (POST /idp/v1/oauth/token on api.morning.co / api.sandbox.morning.dev), and falls back to the legacy POST /account/token automatically if the IDP isn't available for your environment. Refresh on 401 is automatic either way. Reference data (tools group) is served from the shared cache.greeninvoice.co.il host, no auth needed.


Tests — 85 tests, including 23 live E2E (sandbox or production via MORNING_E2E_ENV)
pip install -e ".[test]"

# Unit tests — no network
pytest cli_anything/greeninvoice/tests/test_core.py -v

# Full suite with live sandbox
export MORNING_SANDBOX_ID=<your-id>
export MORNING_SANDBOX_SECRET=<your-secret>
CLI_ANYTHING_FORCE_INSTALLED=1 pytest cli_anything/greeninvoice/tests/ -v

Coverage:

  • 52 unit tests — credentials + per-service host resolution, OAuth token acquisition (camelCase/snake_case shapes, legacy fallback, unreachable-host fallback, TLS errors surfaced, no-fallback on bad keys, MORNING_AUTH_MODE overrides, RFC 6749 error strings), wizard verification (gateway override, core-API rejection propagates), Basic-auth partners, presigned-S3 upload flow (field ordering, no-auth on S3), session locking, payload parsing
  • 10 offline E2E — help, version, error envelopes, --json auth init stream purity, REPL smoke, env-var CI path
  • 23 live sandbox E2E — read-only smoke per resource group, paginated searches, item/supplier mutation round-trips, invoice lifecycle, proforma preview with Hebrew content, expense file upload
  • 3 real bugs caught during development (late-binding, type 305 gate, Tools host/locale)
For AI agents — SKILL.md auto-discovery

morning-cli ships a SKILL.md file auto-discovered by the REPL banner and Claude Code / Cursor. It contains:

  • Full command reference with examples
  • Error code table
  • Agent-specific guidance (always use --json, sandbox defaults, token refresh)
  • Non-interactive auth init for CI

If you're an agent reading this, start with the SKILL.md.

Methodology — cli-anything 7-phase SOP

Built following the cli-anything 7-phase pipeline:

  1. Codebase analysis — parsed the Apiary spec into a 66-endpoint map
  2. Architecture — REPL-first, --json envelopes, session locking, sandbox-first
  3. Implementation — PEP 420 namespace package cli_anything.greeninvoice
  4. Test planning — TEST.md written before tests
  5. Test implementation — unit + live E2E
  6. Test documentation — results appended to TEST.md
  7. PyPI publishingpip install morning-cli

Full SOP: GREENINVOICE.md


Contributing

PRs welcome! Run the tests before submitting:

pip install -e ".[test]"
pytest cli_anything/greeninvoice/tests/test_core.py -v

See open issues for good first contributions.


JangoAI — AI automation for Israeli businesses

Website · GitHub · morning API docs

MIT License · morning-cli is a community project and is not officially affiliated with morning Ltd.

Release files for morning-cli 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for morning-cli 0.2.0
File Size Uploaded
morning_cli-0.2.0.tar.gz 51.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for morning-cli 0.2.0
File Interpreter ABI Platform
morning_cli-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size:103.9 kB

Release files / morning_cli-0.2.0.tar.gz

Download URL morning_cli-0.2.0.tar.gz
Size 51.3 kB
Tags Source
SHA-256 checksum
How to use checksums
36d2930c2c68e158b038a0555cefe8c114e784a501a05f4219e589249153f811
BLAKE2b-256 checksum
How to use checksums
ef242d0598847a4e4c0f3aa81524957ab6179cf86e2650294f4fd12cacadb2d8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.6

Release files / morning_cli-0.2.0-py3-none-any.whl

Download URL morning_cli-0.2.0-py3-none-any.whl
Size 52.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a9bd7e06c699dc3d74deeab12603ea1b77d6bd0908f51a009e23889735bfe4f8
BLAKE2b-256 checksum
How to use checksums
f4952e4a278194100031bd0fa4dc658b323aa321aca12ff407aaa5664615caf4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.6

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page