Server Scripts
A Server Script runs Python on the server when a document event fires. Same purpose as Client Scripts but with full DB access and trusted execution — used for security-critical validation, side effects, and background work.
Creating one
Customize → Server Script → New:
| Script Type | When it runs |
|---|---|
| DocType Event | On a document lifecycle (validate, before_save, on_submit, on_cancel, on_trash) |
| API Method | Exposed at /api/method/<your.path> for external callers |
| Scheduler Event | On a cron schedule (hourly, daily, custom) |
| Permission Query | Returns a SQL fragment to filter list views |
DocType event example
# Triggered on validate of Sales Invoice
if doc.grand_total > 100000 and not doc.approved_by_manager:
frappe.throw(_("Invoices over 100k require manager approval"))
if doc.customer:
customer = frappe.get_doc("Customer", doc.customer)
outstanding = customer.outstanding or 0
if customer.credit_limit and (doc.grand_total + outstanding) > customer.credit_limit:
frappe.throw(_("Customer over credit limit"))
doc is the current document; frappe is the framework module; _() translates strings.
Scheduler example
# Daily: notify accounting of overdue invoices
overdue = frappe.get_all("Sales Invoice", filters={
"due_date": ["<", frappe.utils.nowdate()],
"outstanding_amount": [">", 0],
"docstatus": 1
})
if overdue:
frappe.sendmail(
recipients=["accounts@example.com"],
subject=f"{len(overdue)} overdue invoices",
message="<br>".join(i.name for i in overdue)
)
API method example
# Callable at /api/method/<your.path> — args from request payload
return {"ok": True, "result": frappe.utils.flt(amount) * 1.21}
Sandbox
Server Scripts run in a Python sandbox: no import of arbitrary modules, no file system writes, no subprocess. For unrestricted Python or external dependencies, write a Frappe app instead — see Developers.
Last updated 3 days ago
Was this helpful?