Skip to main content
The Document API provides methods for creating, reading, updating, and deleting documents in ERPNext. All operations interact with the Frappe Framework’s ORM layer.

Getting Documents

frappe.get_doc()

Retrieve a single document from the database.
doctype
string
required
The DocType name (e.g., “Sales Order”, “Customer”, “Item”)
name
string
required
The document name/ID
import frappe

# Get a specific Sales Invoice
invoice = frappe.get_doc("Sales Invoice", "SI-2024-00001")
print(invoice.customer)
print(invoice.grand_total)

# Get a Customer
customer = frappe.get_doc("Customer", "_Test Customer")
print(customer.customer_name)

frappe.get_all()

Get a list of documents with minimal data. Returns only specified fields.
doctype
string
required
The DocType to query
filters
dict
default:"{}"
Filter conditions as dictionary
fields
list
default:"['name']"
List of fields to retrieve
order_by
string
Sort order (e.g., “creation desc”, “modified asc”)
limit
int
Maximum number of records to return
import frappe

# Get all accounts
accounts = frappe.get_all("Account", 
    filters={"company": "_Test Company"},
    fields=["name", "account_name", "account_type"]
)

for account in accounts:
    print(account.name, account.account_name)

frappe.get_list()

Similar to get_all() but with permission checks and additional features.
import frappe

# Get list with permission filtering
items = frappe.get_list("Item",
    filters={"disabled": 0},
    fields=["item_code", "item_name", "stock_uom"],
    order_by="item_name"
)

Creating Documents

frappe.get_doc() with dict

Create a new document by passing a dictionary.
import frappe

# Create a new Contact
contact = frappe.get_doc({
    "doctype": "Contact",
    "first_name": "_Test Contact for _Test Customer",
    "links": [{
        "link_doctype": "Customer",
        "link_name": "_Test Customer"
    }]
})
contact.add_email("[email protected]", is_primary=True)
contact.add_phone("+91 0000000000", is_primary_phone=True)
contact.insert()

Updating Documents

Save Changes

Modify and save existing documents.
import frappe

# Get and update document
company = frappe.get_doc("Company", "_Test Company")
company.monthly_sales_target = 2000
company.total_monthly_sales = 1500
company.save()

Deleting Documents

frappe.delete_doc()

Delete one or multiple documents.
doctype
string
required
The DocType name
name
string | list
required
Document name or list of names to delete
for_reload
bool
default:"False"
Skip some validations during reload
import frappe

# Delete a document
frappe.delete_doc("Lead", "LEAD-2024-00001")

Document Methods

Common Document Operations

import frappe

# Get document and validate
doc = frappe.get_doc("Sales Order", "SO-2024-00001")
doc.validate()  # Run validation hooks

Checking Document Existence

frappe.db.exists()

Check if a document exists before operations.
import frappe

# Check if document exists
if frappe.db.exists("Customer", "_Test Customer"):
    print("Customer exists")

# Check with filters
if frappe.db.exists("Account", {"account_name": "Debtors", "company": "_Test Company"}):
    print("Account found")

Response Structure

Document Object

doctype
string
The DocType name of the document
name
string
Unique identifier of the document
owner
string
User who created the document
creation
datetime
Timestamp when document was created
modified
datetime
Timestamp of last modification
modified_by
string
User who last modified the document
docstatus
int
Document status: 0 (Draft), 1 (Submitted), 2 (Cancelled)

Best Practices

Performance

Use get_all() or get_list() when you only need specific fields. Avoid loading full documents unnecessarily.

Permissions

Use get_list() instead of get_all() when permission checks are required.

Transactions

Wrap multiple operations in frappe.db.commit() for consistency.

Validation

Always call .insert() or .save() to trigger validation hooks and maintain data integrity.

Common Patterns

Get or Create Pattern

import frappe

def get_or_create_contact(email):
    """Get existing contact or create new one"""
    if frappe.db.exists("Contact", {"email_id": email}):
        return frappe.get_doc("Contact", {"email_id": email})
    
    contact = frappe.get_doc({
        "doctype": "Contact",
        "email_id": email,
        "first_name": email.split("@")[0]
    })
    contact.insert()
    return contact

Bulk Operations

import frappe

# Bulk create with error handling
for record in records:
    try:
        doc = frappe.get_doc(record)
        doc.insert()
        frappe.db.commit()
    except Exception as e:
        frappe.db.rollback()
        frappe.log_error(f"Failed to create {record.get('doctype')}: {str(e)}")

Build docs developers (and LLMs) love