Monday is a standalone Frappe app that pushes records to Monday.com boards. It has no ERPNext dependency and works with any Frappe v16 installation.
The app is deliberately one-way: Frappe creates items on Monday, and never reads state back. Nothing on a Monday board is mirrored into a DocType, so there is no reconciliation, no webhook receiver, and no drift between the two systems.
It knows nothing about what it pushes. Deciding when an item should be created, and what its columns contain, is the job of the app that calls it.
monday.sync.enqueue_item() is the whole public surface:
from monday.sync import enqueue_item
enqueue_item(
board_id="1234567890",
group_id="topics", # optional
item_name="ACME — Brochures A5",
column_values={"text_1": "D-2026-08-3268", "numbers": "1500"},
updates=["<b>Note</b><br>Livraison avant le 12/09."], # optional
reference_doctype="CRM Deal", # optional, for traceability
reference_docname="CRM-DEAL-2026-00042",
callback_method="myapp.monday.on_item_created", # optional
)The call returns immediately with a Monday Sync Log name. The push itself runs in a background job enqueued after commit, so a Monday outage can never fail — or roll back — the transaction that triggered it.
Monday expects a different JSON shape per column type: a date is an object, a status is a label, a number is a string. monday.columns.format_value(column_type, value) handles the translation for text, long_text, numbers, date, status, dropdown, email, phone, link and checkbox. Unknown types fall back to plain text.
Empty values are skipped, never sent as empty — pushing a blank would wipe a column a production user may have filled by hand.
Notes are posted in the item's Updates thread, one update per call, rather than crammed into a long-text column. The item id is persisted before the thread is filled, so a failure while posting updates never loses the item.
Monday Sync Log is both the audit trail and the queue. A failed push stays Failed with a next_retry_at, and a scheduled job re-runs it with exponential back-off (1, 5, 15, 60, 240 min) until max_retries. A rate-limited push honours Monday's Retry-After instead.
Every attempt records the request, the response, the HTTP status and the error. A Retry Now button on the log form forces an immediate re-run.
| DocType | Role |
|---|---|
| Monday Settings | Single — API token, API URL and version, retry budget, log retention, connection status |
| Monday Sync Log | One row per push: payload, response, status, retries, source document, resulting item id |
| Method | Role |
|---|---|
monday.api.test_connection |
Validates the token, stores the account it belongs to |
monday.api.get_boards |
Lists the boards reachable with the token |
monday.api.get_board_structure |
Returns a board's columns and groups, with their ids |
Pushing is never exposed over HTTP — it is server-side only.
- Frappe Bench installed and configured
- Frappe v16
- Python ≥ 3.14
- A Monday.com API token with write access to the target board
cd $PATH_TO_YOUR_BENCH
bench get-app git@github.com:future-onprint/monday.git --branch main
bench --site $YOUR_SITE install-app mondayOpen Monday Settings in the desk (/app/monday-settings):
- Paste the API token — Monday.com → avatar → Developers → My access tokens
- Check Enable Monday.com Integration
- Save, then hit Test Connection — the account name is filled in on success
- Show Boards lists every reachable board with its id
The ids a mapping must reference are not the column titles shown in the Monday UI:
bench --site $YOUR_SITE execute monday.api.get_board_structure --kwargs "{'board_id': '1234567890'}"Returns each column's id, title and type, plus the board's groups.
Monday ships a new API version every quarter and retires old ones after about a year. The version is a plain field in Monday Settings (API Version) so an upgrade never requires a release. If pushes start failing with a version error, bump it there.
This project uses pre-commit:
cd apps/monday
pre-commit install| Tool | Role |
|---|---|
ruff |
Python linting and formatting |
eslint |
JavaScript linting |
prettier |
JavaScript / CSS formatting |
pyupgrade |
Python syntax modernization |
AGPL-3.0 © Underscore Blank OÜ