frappe-js-api
Frappe JS API
This is the source of truth for global Frappe JavaScript APIs. All APIs here are available on every desk page — no import needed.
Full option tables, signatures, and advanced patterns: REFERENCE.md
Use-Case Decision Tree
"I need to call the server"
Is async and you only need r.message?
YES → frappe.xcall(method, args) ← returns Promise<value>
NO → frappe.call({ method, args, callback, freeze, btn, … }) ← jQuery deferred
"I need to read/write data without opening a form"
Read one field from a doc? → frappe.db.get_value(doctype, name_or_filters, fieldname)
Read multiple fields? → frappe.db.get_value(doctype, filters, [f1, f2, …])
Read a list of docs? → frappe.db.get_list(doctype, { fields, filters, limit, … })
Check if a doc exists? → frappe.db.exists(doctype, name)
Count docs? → frappe.db.count(doctype, { filters })
Read a Single doctype field? → frappe.db.get_single_value(doctype, field)
Persist a field change? → frappe.db.set_value(doctype, name, fieldname, value)
Read from LOCAL store (no server)? → frappe.model.get_value(doctype, name, fieldname)
frappe.model.get_doc(doctype, name)
"I need to show a message or feedback"
Short toast / alert banner? → frappe.show_alert(message_or_opts, seconds)
Modal message box? → frappe.msgprint(message_or_opts)
Ask user yes/no? → frappe.confirm(message, onYes, onNo)
Validation error (throws)? → frappe.throw(message_or_opts)
Long-running progress bar? → frappe.show_progress(title, count, total, description)
"I need user input"
Single-field quick prompt? → frappe.prompt(label_or_field, callback, title)
Multiple-field form? → new frappe.ui.Dialog({ fields, primary_action })
"I need to work with dates"
Today's date? → frappe.datetime.get_today() // "YYYY-MM-DD"
Current datetime? → frappe.datetime.now_datetime()
Add/subtract days? → frappe.datetime.add_days(date, n)
Diff in days? → frappe.datetime.get_diff(d1, d2)
Month/week/year start or end? → frappe.datetime.month_start() / month_end() / …
Format for display? → frappe.datetime.str_to_user(date_string)
"I need session / user context"
Current user email? → frappe.session.user
User's default company? → frappe.defaults.get_user_default("Company")
User's roles? → frappe.boot.user.roles
System currency/date format? → frappe.boot.sysdefaults.*
"I need to format a value"
frappe.format(value, { fieldtype: "Currency", options: "USD" }, {}, doc)
frappe.format(value, { fieldtype: "Date" })
frappe.format(value, { fieldtype: "Percent" })
"I need to navigate"
Open a form? → frappe.set_route("Form", doctype, name)
Open a list? → frappe.set_route("List", doctype)
Open in new tab? → frappe.open_in_new_tab = true; frappe.set_route(…)
Get a form URL? → frappe.utils.get_form_link(doctype, name)
"I need realtime / push events"
Listen for a server push event? → frappe.realtime.on("event_name", callback)
Stop listening? → frappe.realtime.off("event_name", callback)
Subscribe to doc updates? → frappe.realtime.doc_subscribe(doctype, name)
Quick API Index
| API | One-liner |
|---|---|
frappe.call |
Server call, full options (freeze, btn, error, always) |
frappe.xcall |
Server call, returns Promise resolving to r.message |
frappe.db.get_value |
Fetch field(s) from a doc by name or filter |
frappe.db.get_list |
Fetch list of docs with fields/filters/limit |
frappe.db.exists |
Check if doc exists, returns Promise |
frappe.db.count |
Count docs matching filters |
frappe.db.set_value |
Persist field change immediately (bypasses form) |
frappe.db.get_single_value |
Read Single doctype field |
frappe.model.get_value |
Local store read (no server) |
frappe.model.set_value |
Local store write + fires triggers |
frappe.model.get_doc |
Get doc from local locals store |
frappe.new_doc |
Open Quick Entry / new form for doctype |
frappe.msgprint |
Modal message dialog |
frappe.confirm |
Yes/No confirm dialog |
frappe.show_alert / frappe.toast |
Toast notification banner |
frappe.throw |
Show error and throw JS exception |
frappe.prompt |
Quick single- or multi-field input dialog |
frappe.ui.Dialog |
Full custom dialog with fields |
frappe.show_progress |
Progress bar dialog |
frappe.datetime.* |
Date/time utilities |
frappe.defaults.* |
User/global defaults |
frappe.session.* |
Current user session info |
frappe.boot.* |
Boot-time config and user metadata |
frappe.format |
Format a value by fieldtype for display |
frappe.set_route |
Navigate to a desk route |
frappe.realtime.* |
Socket.io event pub/sub |
frappe.utils.* |
Misc helpers (links, clipboard, debounce, …) |
frappe.provide |
Define a global namespace safely |
Common Gotchas
frappe.callvsfrappe.xcall:frappe.callgives you the fullrresponse and works with jQuery deferreds;frappe.xcallreturnsr.messagedirectly as a native Promise. Usexcallfor cleanasync/awaitcode.frappe.model.*is LOCAL-ONLY. It reads/writeslocals[doctype][name], the in-memory form store. It never hits the server unless acallbackis passed toget_value.frappe.db.set_valuebypasses form validation and triggers — it callsfrappe.client.set_valuedirectly. Usefrm.set_valueon the form if you need form triggers to fire.frappe.datetime.add_daysreturns moment's default output format, not"YYYY-MM-DD". Wrap withfrappe.datetime.str_to_user()for display.frappe.format_valuedoes not exist. Usefrappe.format(value, df, options, doc).frappe.utils.now(),.nowdate(),.add_days(),.diff_in_days(),.money_in_words()do NOT exist. Usefrappe.datetime.*equivalents.frappe.defaults.set_defaultdoes not exist in JS. Usefrappe.defaults.set_user_default_localfor local-only changes.frappe.open_in_new_tabis a flag, not a function. Set it totruebeforefrappe.set_route, then it auto-resets.
More from kehwar/skills
to-prd
Turn the current conversation context into a PRD and publish it to Beads. Use when user wants to create a PRD from the current context.
9frappe-standard-script-report-view
Expert guidance for writing the .js controller for a Frappe Standard Script Report. Use when defining report filters, implementing formatter callbacks, adding onload toolbar buttons, setting default filter values, using get_datatable_options, or after_datatable_render hooks.
3sap-dtw-expert
Expert guidance for producing correct DTW (Data Transfer Workbench) import files for SAP Business One. Use when recommending templates for bulk import operations, generating TSV files from the bundled templates, understanding multi-table object requirements, identifying mandatory vs optional columns, adding custom fields, or choosing between DTW and Service Layer for a given task.
2frappe-doctype-form-view
Expert guidance for implementing Frappe DocType JavaScript form controllers (.js app files). Covers the complete lifecycle hook execution order (setup/onload/refresh) with explicit placement rules, frm object API (fields_dict, set_query, set_value, toggle_display/reqd/enable, add_custom_button, frm.trigger), frappe.call for server methods, frappe.prompt and frappe.ui.Dialog for user input dialogs, frappe.show_progress for progress feedback, child table APIs, and reusable helper code via frappe.ui.form.Controller subclasses (extend_cscript pattern) to avoid global scope pollution. Use when writing or debugging .js controller files, choosing which hook to use, adding custom buttons, building dialogs, running server methods, triggering events programmatically, sharing logic across event handlers, or fixing bugs caused by logic placed in the wrong hook.
2frappe-doctype-controller
Expert guidance for implementing Frappe DocType Python controllers. Covers the complete hook execution order for insert, save, submit, cancel, delete, load, and rename operations; context guards (is_new(), docstatus, flags, _action); hook placement rules (before_validate vs before_insert vs before_save); detecting field changes with get_doc_before_save(); Document API (insert/save/submit/cancel/delete/rename params); bypassing hooks with db_set vs frappe.db.set_value; and error-raising conventions. Use when writing or debugging .py controller files, choosing which hook to implement, or fixing bugs caused by logic placed in the wrong hook.
2