📚 Complete API Documentation Created
Files Generated:
1. API_ENDPOINTS.md (1,171 lines)
- Complete documentation of all 771 DocTypes in ERPNext
- Organized by 37 modules
- Sample record names for each DocType
- Full REST endpoint patterns
- Examples and usage instructions
2. generate_api_docs.py
- Python script to auto-discover and document all API endpoints
- Fetches live data from your ERPNext instance
- Can be re-run anytime to update documentation
3. discover_api_endpoints.sh
- Bash alternative for API discovery
- Lightweight script for quick checks
4. test_api.sh
- Ready-to-use API testing script
- Demonstrates authentication and common API calls
Key Features of the Documentation:
Complete Coverage:
- ✅ All 771 DocTypes documented
- ✅ 37 modules categorized
- ✅ Sample data for each DocType
- ✅ Single vs Standard vs Submittable types identified
- ✅ Child tables marked
API Endpoint Patterns for Each DocType:
# Standard DocTypes (e.g., Item, Customer)
GET /api/resource/{DocType} # List all
GET /api/resource/{DocType}/{name} # Get single
POST /api/resource/{DocType} # Create new
PUT /api/resource/{DocType}/{name} # Update
DELETE /api/resource/{DocType}/{name} # Delete
# Single DocTypes (e.g., System Settings)
GET /api/resource/{DocType}/{DocType} # Get singleton
Sample DocTypes by Category:
Standard DocTypes (most common):
- Customer, Item, Sales Order, Purchase Order, etc.
Single DocTypes (singletons):
- System Settings, Accounts Settings, Stock Settings, etc.
Submittable DocTypes (workflow):
- Sales Invoice, Purchase Invoice, Journal Entry, etc.
Child Tables (part of parent):
- Sales Order Item, Purchase Order Item, etc.
This commit is contained in:
parent
44a463d99c
commit
afe596e5ef
1171
API_ENDPOINTS.md
Normal file
1171
API_ENDPOINTS.md
Normal file
File diff suppressed because it is too large
Load Diff
297
API_GUIDE.md
Normal file
297
API_GUIDE.md
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
# ERPNext API Access Guide
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
ERPNext provides comprehensive REST APIs for all its modules. The APIs follow RESTful conventions and return JSON responses.
|
||||||
|
|
||||||
|
**Important**: There is no browsable API index page at `/api/`. You must access specific endpoints directly.
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
|
||||||
|
### Base URL
|
||||||
|
```
|
||||||
|
http://localhost:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
### Common API Endpoints
|
||||||
|
|
||||||
|
#### 1. **Authentication**
|
||||||
|
```bash
|
||||||
|
# Login
|
||||||
|
POST http://localhost:8080/api/method/login
|
||||||
|
{
|
||||||
|
"usr": "Administrator",
|
||||||
|
"pwd": "LocalDev123!"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. **Resource APIs**
|
||||||
|
All DocTypes (database tables) in ERPNext are accessible via REST:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Get list of items
|
||||||
|
GET http://localhost:8080/api/resource/Item
|
||||||
|
|
||||||
|
# Get specific item
|
||||||
|
GET http://localhost:8080/api/resource/Item/{item_name}
|
||||||
|
|
||||||
|
# Create new item
|
||||||
|
POST http://localhost:8080/api/resource/Item
|
||||||
|
|
||||||
|
# Update item
|
||||||
|
PUT http://localhost:8080/api/resource/Item/{item_name}
|
||||||
|
|
||||||
|
# Delete item
|
||||||
|
DELETE http://localhost:8080/api/resource/Item/{item_name}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. **Method APIs**
|
||||||
|
Custom server methods can be called:
|
||||||
|
```bash
|
||||||
|
POST http://localhost:8080/api/method/{method_path}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Authentication Methods
|
||||||
|
|
||||||
|
### 1. **Session-based Authentication**
|
||||||
|
After login, a session cookie is set which is used for subsequent requests.
|
||||||
|
|
||||||
|
### 2. **Token-based Authentication**
|
||||||
|
Generate API keys from the user settings:
|
||||||
|
|
||||||
|
1. Login to ERPNext UI
|
||||||
|
2. Go to Settings → My Settings
|
||||||
|
3. Scroll to "API Access" section
|
||||||
|
4. Generate API Secret
|
||||||
|
5. Use in requests:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -H "Authorization: token api_key:api_secret" \
|
||||||
|
http://localhost:8080/api/resource/Item
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. **Basic Authentication**
|
||||||
|
```bash
|
||||||
|
curl -u Administrator:LocalDev123! \
|
||||||
|
http://localhost:8080/api/resource/Item
|
||||||
|
```
|
||||||
|
|
||||||
|
## Live API Documentation
|
||||||
|
|
||||||
|
### 1. **Exploring Available DocTypes**
|
||||||
|
Get a list of all available DocTypes (tables/resources):
|
||||||
|
```bash
|
||||||
|
# After login
|
||||||
|
curl -b cookies.txt http://localhost:8080/api/resource/DocType
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. **Swagger/OpenAPI Documentation**
|
||||||
|
While ERPNext doesn't have built-in Swagger, you can explore APIs through:
|
||||||
|
|
||||||
|
- **Frappe Web UI**: After logging in, press `Ctrl+G` (or `Cmd+G` on Mac) to open the awesome bar and type any DocType name
|
||||||
|
- **Developer Console**: Access via browser DevTools to see API calls made by the UI
|
||||||
|
|
||||||
|
### 3. **Interactive Console**
|
||||||
|
Access the Python console to explore APIs:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Enter the backend container
|
||||||
|
docker exec -it erpnext /bin/bash
|
||||||
|
|
||||||
|
# Start bench console
|
||||||
|
bench --site frontend console
|
||||||
|
|
||||||
|
# Example commands in console:
|
||||||
|
>>> frappe.get_all('Item')
|
||||||
|
>>> frappe.get_doc('Item', 'ITEM-001')
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common API Operations
|
||||||
|
|
||||||
|
### Customer Management
|
||||||
|
```bash
|
||||||
|
# List customers
|
||||||
|
GET /api/resource/Customer
|
||||||
|
|
||||||
|
# Create customer
|
||||||
|
POST /api/resource/Customer
|
||||||
|
{
|
||||||
|
"customer_name": "Test Customer",
|
||||||
|
"customer_type": "Company",
|
||||||
|
"customer_group": "All Customer Groups",
|
||||||
|
"territory": "All Territories"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Item Management
|
||||||
|
```bash
|
||||||
|
# List items
|
||||||
|
GET /api/resource/Item
|
||||||
|
|
||||||
|
# Create item
|
||||||
|
POST /api/resource/Item
|
||||||
|
{
|
||||||
|
"item_code": "TEST-001",
|
||||||
|
"item_name": "Test Item",
|
||||||
|
"item_group": "All Item Groups",
|
||||||
|
"stock_uom": "Nos"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Sales Order
|
||||||
|
```bash
|
||||||
|
# Create sales order
|
||||||
|
POST /api/resource/Sales%20Order
|
||||||
|
{
|
||||||
|
"customer": "Test Customer",
|
||||||
|
"delivery_date": "2024-12-31",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"item_code": "TEST-001",
|
||||||
|
"qty": 10,
|
||||||
|
"rate": 100
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Response Format
|
||||||
|
|
||||||
|
### Success Response
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
// Response data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Error Response
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"exc_type": "ValidationError",
|
||||||
|
"exception": "Error details",
|
||||||
|
"_server_messages": "..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing APIs
|
||||||
|
|
||||||
|
### Using cURL
|
||||||
|
```bash
|
||||||
|
# Login and save cookies
|
||||||
|
curl -c cookies.txt -X POST \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"usr":"Administrator","pwd":"LocalDev123!"}' \
|
||||||
|
http://localhost:8080/api/method/login
|
||||||
|
|
||||||
|
# Use cookies for subsequent requests
|
||||||
|
curl -b cookies.txt \
|
||||||
|
http://localhost:8080/api/resource/Item
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using Postman
|
||||||
|
1. Import ERPNext collection (create your own based on endpoints above)
|
||||||
|
2. Set base URL to `http://localhost:8080`
|
||||||
|
3. Configure authentication in collection settings
|
||||||
|
|
||||||
|
### Using Python
|
||||||
|
```python
|
||||||
|
import requests
|
||||||
|
|
||||||
|
# Login
|
||||||
|
session = requests.Session()
|
||||||
|
login_response = session.post(
|
||||||
|
'http://localhost:8080/api/method/login',
|
||||||
|
json={'usr': 'Administrator', 'pwd': 'LocalDev123!'}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get items
|
||||||
|
items = session.get('http://localhost:8080/api/resource/Item')
|
||||||
|
print(items.json())
|
||||||
|
```
|
||||||
|
|
||||||
|
## Advanced Features
|
||||||
|
|
||||||
|
### 1. **Filters**
|
||||||
|
```bash
|
||||||
|
# Filter with conditions
|
||||||
|
GET /api/resource/Item?filters=[["item_group","=","Products"]]
|
||||||
|
|
||||||
|
# Multiple filters
|
||||||
|
GET /api/resource/Item?filters=[["item_group","=","Products"],["disabled","=",0]]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. **Field Selection**
|
||||||
|
```bash
|
||||||
|
# Select specific fields
|
||||||
|
GET /api/resource/Item?fields=["item_code","item_name","standard_rate"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. **Pagination**
|
||||||
|
```bash
|
||||||
|
# Limit and offset
|
||||||
|
GET /api/resource/Item?limit_start=0&limit_page_length=20
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. **Sorting**
|
||||||
|
```bash
|
||||||
|
# Order by field
|
||||||
|
GET /api/resource/Item?order_by=modified%20desc
|
||||||
|
```
|
||||||
|
|
||||||
|
## WebSocket API
|
||||||
|
|
||||||
|
ERPNext also provides WebSocket connections for real-time updates:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Connect to WebSocket
|
||||||
|
const socket = io('http://localhost:8080', {
|
||||||
|
withCredentials: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Listen for events
|
||||||
|
socket.on('connect', () => {
|
||||||
|
console.log('Connected to ERPNext WebSocket');
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Rate Limiting
|
||||||
|
|
||||||
|
ERPNext implements rate limiting for API calls:
|
||||||
|
- Default: 60 requests per minute per IP
|
||||||
|
- Can be configured in site_config.json
|
||||||
|
|
||||||
|
## Security Best Practices
|
||||||
|
|
||||||
|
1. **Always use HTTPS in production**
|
||||||
|
2. **Generate and use API tokens instead of passwords**
|
||||||
|
3. **Implement IP whitelisting for API access**
|
||||||
|
4. **Regular token rotation**
|
||||||
|
5. **Monitor API usage logs**
|
||||||
|
|
||||||
|
## Debugging
|
||||||
|
|
||||||
|
### Enable Debug Mode
|
||||||
|
```bash
|
||||||
|
# In the backend container
|
||||||
|
bench --site frontend set-config developer_mode 1
|
||||||
|
bench --site frontend clear-cache
|
||||||
|
```
|
||||||
|
|
||||||
|
### View API Logs
|
||||||
|
```bash
|
||||||
|
# Check frappe logs
|
||||||
|
docker exec -it erpnext tail -f sites/frontend/logs/frappe.log
|
||||||
|
```
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Frappe REST API Documentation](https://frappeframework.com/docs/user/en/api/rest)
|
||||||
|
- [ERPNext API Reference](https://docs.erpnext.com/docs/user/manual/en/api)
|
||||||
|
- [Frappe Client Scripts](https://frappeframework.com/docs/user/en/desk/scripting/client-script)
|
||||||
|
|
||||||
|
## Need Help?
|
||||||
|
|
||||||
|
- Check the logs: `docker compose logs -f backend`
|
||||||
|
- Access the console: `docker exec -it erpnext bench --site frontend console`
|
||||||
|
- Visit the [ERPNext Forum](https://discuss.erpnext.com/) for community support
|
||||||
25
CLAUDE.md
25
CLAUDE.md
@ -114,6 +114,31 @@ When changing `APP_VERSION` in `.env`:
|
|||||||
- **Network**: All services communicate through the `erpnext-local` Docker network
|
- **Network**: All services communicate through the `erpnext-local` Docker network
|
||||||
- **Default Credentials**: Administrator / LocalDev123!
|
- **Default Credentials**: Administrator / LocalDev123!
|
||||||
|
|
||||||
|
## API Development
|
||||||
|
|
||||||
|
### Accessing APIs
|
||||||
|
ERPNext provides REST APIs accessible at `http://localhost:8080/api/`
|
||||||
|
|
||||||
|
### Common API Endpoints
|
||||||
|
- **Login**: `POST /api/method/login`
|
||||||
|
- **Resources**: `/api/resource/{DocType}`
|
||||||
|
- **Methods**: `/api/method/{method_path}`
|
||||||
|
|
||||||
|
### Testing APIs
|
||||||
|
```bash
|
||||||
|
# Login and get session
|
||||||
|
curl -c cookies.txt -X POST \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"usr":"Administrator","pwd":"LocalDev123!"}' \
|
||||||
|
http://localhost:8080/api/method/login
|
||||||
|
|
||||||
|
# Use session for API calls
|
||||||
|
curl -b cookies.txt http://localhost:8080/api/resource/Item
|
||||||
|
```
|
||||||
|
|
||||||
|
### API Documentation
|
||||||
|
See [API_GUIDE.md](API_GUIDE.md) for comprehensive API documentation.
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### Port Conflicts
|
### Port Conflicts
|
||||||
|
|||||||
11
README.md
11
README.md
@ -165,10 +165,21 @@ This deployment uses a microservices architecture with the following containers:
|
|||||||
- **configurator**: Initial configuration (runs once)
|
- **configurator**: Initial configuration (runs once)
|
||||||
- **create-site**: Site creation (runs once)
|
- **create-site**: Site creation (runs once)
|
||||||
|
|
||||||
|
## API Access
|
||||||
|
|
||||||
|
ERPNext provides comprehensive REST APIs for integration. See [API_GUIDE.md](API_GUIDE.md) for detailed documentation on:
|
||||||
|
- Authentication methods
|
||||||
|
- REST API endpoints
|
||||||
|
- WebSocket connections
|
||||||
|
- API testing examples
|
||||||
|
|
||||||
|
Quick access: `http://localhost:8080/api/`
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
- [ERPNext Documentation](https://docs.erpnext.com/)
|
- [ERPNext Documentation](https://docs.erpnext.com/)
|
||||||
- [Frappe Framework Documentation](https://frappeframework.com/docs)
|
- [Frappe Framework Documentation](https://frappeframework.com/docs)
|
||||||
|
- [Frappe REST API Documentation](https://frappeframework.com/docs/user/en/api/rest)
|
||||||
- [Docker Compose Documentation](https://docs.docker.com/compose/)
|
- [Docker Compose Documentation](https://docs.docker.com/compose/)
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|||||||
190
discover_api_endpoints.sh
Executable file
190
discover_api_endpoints.sh
Executable file
@ -0,0 +1,190 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# ERPNext API Discovery Script
|
||||||
|
# This script discovers all available DocTypes and their endpoints
|
||||||
|
|
||||||
|
API_URL="http://localhost:8080"
|
||||||
|
USERNAME="Administrator"
|
||||||
|
PASSWORD="LocalDev123!"
|
||||||
|
OUTPUT_FILE="API_ENDPOINTS.md"
|
||||||
|
|
||||||
|
echo "======================================"
|
||||||
|
echo "ERPNext API Discovery Script"
|
||||||
|
echo "======================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Login
|
||||||
|
echo "Logging in..."
|
||||||
|
curl -s -c cookies.txt -X POST \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{\"usr\":\"$USERNAME\",\"pwd\":\"$PASSWORD\"}" \
|
||||||
|
$API_URL/api/method/login > /dev/null
|
||||||
|
|
||||||
|
# Get all DocTypes
|
||||||
|
echo "Fetching all DocTypes..."
|
||||||
|
ALL_DOCTYPES=$(curl -s -b cookies.txt "$API_URL/api/resource/DocType?limit_page_length=1000&fields=\[\"name\",\"module\",\"is_submittable\",\"issingle\"\]" | jq -r '.data')
|
||||||
|
|
||||||
|
# Start creating the documentation
|
||||||
|
cat > $OUTPUT_FILE << 'EOF'
|
||||||
|
# ERPNext API Endpoints Documentation
|
||||||
|
|
||||||
|
Generated on: $(date)
|
||||||
|
|
||||||
|
This document provides a comprehensive list of all available API endpoints in ERPNext.
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
All API calls require authentication. First, login to get a session:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -c cookies.txt -X POST \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"usr":"Administrator","pwd":"your_password"}' \
|
||||||
|
http://localhost:8080/api/method/login
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Endpoint Pattern
|
||||||
|
|
||||||
|
All DocTypes follow the same RESTful pattern:
|
||||||
|
|
||||||
|
- **List/Search**: `GET /api/resource/{DocType}`
|
||||||
|
- **Get Single**: `GET /api/resource/{DocType}/{name}`
|
||||||
|
- **Create**: `POST /api/resource/{DocType}`
|
||||||
|
- **Update**: `PUT /api/resource/{DocType}/{name}`
|
||||||
|
- **Delete**: `DELETE /api/resource/{DocType}/{name}`
|
||||||
|
|
||||||
|
## Available DocTypes and Endpoints
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "" >> $OUTPUT_FILE
|
||||||
|
echo "Processing DocTypes and getting sample data..."
|
||||||
|
|
||||||
|
# Process each module
|
||||||
|
MODULES=$(echo "$ALL_DOCTYPES" | jq -r '.[].module' | sort -u)
|
||||||
|
|
||||||
|
for MODULE in $MODULES; do
|
||||||
|
echo "Processing module: $MODULE"
|
||||||
|
echo "" >> $OUTPUT_FILE
|
||||||
|
echo "### Module: $MODULE" >> $OUTPUT_FILE
|
||||||
|
echo "" >> $OUTPUT_FILE
|
||||||
|
echo "| DocType | Single/List | Sample Names | Endpoints |" >> $OUTPUT_FILE
|
||||||
|
echo "|---------|-------------|--------------|-----------|" >> $OUTPUT_FILE
|
||||||
|
|
||||||
|
# Get DocTypes for this module
|
||||||
|
MODULE_DOCTYPES=$(echo "$ALL_DOCTYPES" | jq -r ".[] | select(.module==\"$MODULE\") | .name")
|
||||||
|
|
||||||
|
for DOCTYPE in $MODULE_DOCTYPES; do
|
||||||
|
# URL encode the DocType name
|
||||||
|
DOCTYPE_ENCODED=$(echo "$DOCTYPE" | sed 's/ /%20/g')
|
||||||
|
|
||||||
|
# Check if it's a single DocType
|
||||||
|
IS_SINGLE=$(echo "$ALL_DOCTYPES" | jq -r ".[] | select(.name==\"$DOCTYPE\") | .issingle")
|
||||||
|
|
||||||
|
# Get sample records (limit to 3)
|
||||||
|
SAMPLE_RECORDS=$(curl -s -b cookies.txt "$API_URL/api/resource/$DOCTYPE_ENCODED?limit_page_length=3&fields=\[\"name\"\]" 2>/dev/null | jq -r '.data[]?.name' 2>/dev/null | tr '\n' ', ' | sed 's/,$//' | sed 's/,/, /g')
|
||||||
|
|
||||||
|
if [ "$IS_SINGLE" == "1" ]; then
|
||||||
|
TYPE="Single"
|
||||||
|
ENDPOINTS="\`GET /api/resource/$DOCTYPE/$DOCTYPE\`"
|
||||||
|
SAMPLE_RECORDS="$DOCTYPE"
|
||||||
|
else
|
||||||
|
TYPE="List"
|
||||||
|
ENDPOINTS="\`/api/resource/$DOCTYPE\`"
|
||||||
|
if [ -z "$SAMPLE_RECORDS" ]; then
|
||||||
|
SAMPLE_RECORDS="No records"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escape pipe characters in sample records
|
||||||
|
SAMPLE_RECORDS=$(echo "$SAMPLE_RECORDS" | sed 's/|/\\|/g')
|
||||||
|
|
||||||
|
# Truncate if too long
|
||||||
|
if [ ${#SAMPLE_RECORDS} -gt 50 ]; then
|
||||||
|
SAMPLE_RECORDS="${SAMPLE_RECORDS:0:47}..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "| $DOCTYPE | $TYPE | $SAMPLE_RECORDS | $ENDPOINTS |" >> $OUTPUT_FILE
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
# Add common query parameters section
|
||||||
|
cat >> $OUTPUT_FILE << 'EOF'
|
||||||
|
|
||||||
|
## Common Query Parameters
|
||||||
|
|
||||||
|
### For List Endpoints
|
||||||
|
|
||||||
|
| Parameter | Description | Example |
|
||||||
|
|-----------|-------------|---------|
|
||||||
|
| `fields` | Select specific fields | `fields=["name","status"]` |
|
||||||
|
| `filters` | Filter results | `filters=[["status","=","Active"]]` |
|
||||||
|
| `limit_start` | Pagination offset | `limit_start=0` |
|
||||||
|
| `limit_page_length` | Page size | `limit_page_length=20` |
|
||||||
|
| `order_by` | Sort results | `order_by=modified desc` |
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
#### Get list with filters
|
||||||
|
```bash
|
||||||
|
curl -b cookies.txt \
|
||||||
|
"http://localhost:8080/api/resource/Item?filters=[[\"item_group\",\"=\",\"Products\"]]&fields=[\"item_code\",\"item_name\"]"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Get single document
|
||||||
|
```bash
|
||||||
|
curl -b cookies.txt \
|
||||||
|
"http://localhost:8080/api/resource/User/Administrator"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Create new document
|
||||||
|
```bash
|
||||||
|
curl -b cookies.txt -X POST \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"doctype":"Item","item_code":"TEST-001","item_name":"Test Item","item_group":"Products","stock_uom":"Nos"}' \
|
||||||
|
"http://localhost:8080/api/resource/Item"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Update document
|
||||||
|
```bash
|
||||||
|
curl -b cookies.txt -X PUT \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"item_name":"Updated Test Item"}' \
|
||||||
|
"http://localhost:8080/api/resource/Item/TEST-001"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Delete document
|
||||||
|
```bash
|
||||||
|
curl -b cookies.txt -X DELETE \
|
||||||
|
"http://localhost:8080/api/resource/Item/TEST-001"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Special Endpoints
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
- `POST /api/method/login` - Login
|
||||||
|
- `POST /api/method/logout` - Logout
|
||||||
|
|
||||||
|
### File Upload
|
||||||
|
- `POST /api/method/upload_file` - Upload files
|
||||||
|
|
||||||
|
### Reports
|
||||||
|
- `GET /api/method/frappe.desk.query_report.run` - Run reports
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
1. **Single DocTypes**: These DocTypes have only one record (like System Settings) and use their name directly in the URL
|
||||||
|
2. **URL Encoding**: DocType names with spaces must be URL encoded (e.g., "Sales Order" becomes "Sales%20Order")
|
||||||
|
3. **Permissions**: Access to DocTypes depends on user permissions
|
||||||
|
4. **Rate Limiting**: Default rate limit is 60 requests per minute
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "======================================"
|
||||||
|
echo "Discovery complete!"
|
||||||
|
echo "Documentation saved to: $OUTPUT_FILE"
|
||||||
|
echo "======================================"
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
rm -f cookies.txt
|
||||||
319
generate_api_docs.py
Executable file
319
generate_api_docs.py
Executable file
@ -0,0 +1,319 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
from datetime import datetime
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
API_URL = "http://localhost:8080"
|
||||||
|
USERNAME = "Administrator"
|
||||||
|
PASSWORD = "LocalDev123!"
|
||||||
|
|
||||||
|
def login():
|
||||||
|
"""Login and return session"""
|
||||||
|
session = requests.Session()
|
||||||
|
response = session.post(
|
||||||
|
f"{API_URL}/api/method/login",
|
||||||
|
json={"usr": USERNAME, "pwd": PASSWORD}
|
||||||
|
)
|
||||||
|
if response.status_code == 200:
|
||||||
|
print("✓ Logged in successfully")
|
||||||
|
return session
|
||||||
|
else:
|
||||||
|
print("✗ Login failed")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_all_doctypes(session):
|
||||||
|
"""Fetch all DocTypes"""
|
||||||
|
response = session.get(
|
||||||
|
f"{API_URL}/api/resource/DocType",
|
||||||
|
params={
|
||||||
|
"limit_page_length": 1000,
|
||||||
|
"fields": json.dumps(["name", "module", "issingle", "is_submittable", "istable"])
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if response.status_code == 200:
|
||||||
|
return response.json().get("data", [])
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_sample_records(session, doctype, limit=3):
|
||||||
|
"""Get sample record names for a DocType"""
|
||||||
|
try:
|
||||||
|
# URL encode the DocType name
|
||||||
|
doctype_encoded = urllib.parse.quote(doctype)
|
||||||
|
response = session.get(
|
||||||
|
f"{API_URL}/api/resource/{doctype_encoded}",
|
||||||
|
params={
|
||||||
|
"limit_page_length": limit,
|
||||||
|
"fields": json.dumps(["name"])
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json().get("data", [])
|
||||||
|
return [record.get("name", "") for record in data]
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return []
|
||||||
|
|
||||||
|
def generate_documentation(session):
|
||||||
|
"""Generate comprehensive API documentation"""
|
||||||
|
|
||||||
|
print("Fetching all DocTypes...")
|
||||||
|
doctypes = get_all_doctypes(session)
|
||||||
|
print(f"Found {len(doctypes)} DocTypes")
|
||||||
|
|
||||||
|
# Group by module
|
||||||
|
modules = {}
|
||||||
|
for doctype in doctypes:
|
||||||
|
module = doctype.get("module", "Unknown")
|
||||||
|
if module not in modules:
|
||||||
|
modules[module] = []
|
||||||
|
modules[module].append(doctype)
|
||||||
|
|
||||||
|
# Sort modules
|
||||||
|
sorted_modules = sorted(modules.keys())
|
||||||
|
|
||||||
|
# Generate markdown
|
||||||
|
doc = []
|
||||||
|
doc.append("# ERPNext API Endpoints Documentation")
|
||||||
|
doc.append("")
|
||||||
|
doc.append(f"Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||||
|
doc.append("")
|
||||||
|
doc.append("This document provides a comprehensive list of all available API endpoints in ERPNext.")
|
||||||
|
doc.append("")
|
||||||
|
|
||||||
|
# Authentication section
|
||||||
|
doc.append("## Authentication")
|
||||||
|
doc.append("")
|
||||||
|
doc.append("All API calls require authentication. First, login to get a session:")
|
||||||
|
doc.append("")
|
||||||
|
doc.append("```bash")
|
||||||
|
doc.append("curl -c cookies.txt -X POST \\")
|
||||||
|
doc.append(" -H \"Content-Type: application/json\" \\")
|
||||||
|
doc.append(" -d '{\"usr\":\"Administrator\",\"pwd\":\"your_password\"}' \\")
|
||||||
|
doc.append(" http://localhost:8080/api/method/login")
|
||||||
|
doc.append("```")
|
||||||
|
doc.append("")
|
||||||
|
|
||||||
|
# API Pattern section
|
||||||
|
doc.append("## API Endpoint Pattern")
|
||||||
|
doc.append("")
|
||||||
|
doc.append("All DocTypes follow the same RESTful pattern:")
|
||||||
|
doc.append("")
|
||||||
|
doc.append("- **List/Search**: `GET /api/resource/{DocType}`")
|
||||||
|
doc.append("- **Get Single**: `GET /api/resource/{DocType}/{name}`")
|
||||||
|
doc.append("- **Create**: `POST /api/resource/{DocType}`")
|
||||||
|
doc.append("- **Update**: `PUT /api/resource/{DocType}/{name}`")
|
||||||
|
doc.append("- **Delete**: `DELETE /api/resource/{DocType}/{name}`")
|
||||||
|
doc.append("")
|
||||||
|
|
||||||
|
# Table of Contents
|
||||||
|
doc.append("## Table of Contents")
|
||||||
|
doc.append("")
|
||||||
|
for module in sorted_modules:
|
||||||
|
doc.append(f"- [{module}](#{module.lower().replace(' ', '-')})")
|
||||||
|
doc.append("")
|
||||||
|
|
||||||
|
# DocTypes by Module
|
||||||
|
doc.append("## Available DocTypes by Module")
|
||||||
|
doc.append("")
|
||||||
|
|
||||||
|
total_processed = 0
|
||||||
|
for module in sorted_modules:
|
||||||
|
print(f"\nProcessing module: {module}")
|
||||||
|
doc.append(f"### {module}")
|
||||||
|
doc.append("")
|
||||||
|
doc.append("| DocType | Type | Sample Names | API Endpoints |")
|
||||||
|
doc.append("|---------|------|--------------|---------------|")
|
||||||
|
|
||||||
|
module_doctypes = sorted(modules[module], key=lambda x: x.get("name", ""))
|
||||||
|
|
||||||
|
for doctype_info in module_doctypes:
|
||||||
|
doctype = doctype_info.get("name", "")
|
||||||
|
issingle = doctype_info.get("issingle", 0)
|
||||||
|
istable = doctype_info.get("istable", 0)
|
||||||
|
is_submittable = doctype_info.get("is_submittable", 0)
|
||||||
|
|
||||||
|
# Determine type
|
||||||
|
if issingle:
|
||||||
|
dtype = "Single"
|
||||||
|
elif istable:
|
||||||
|
dtype = "Child Table"
|
||||||
|
elif is_submittable:
|
||||||
|
dtype = "Submittable"
|
||||||
|
else:
|
||||||
|
dtype = "Standard"
|
||||||
|
|
||||||
|
# Get sample records
|
||||||
|
if issingle:
|
||||||
|
samples = [doctype]
|
||||||
|
elif istable:
|
||||||
|
samples = ["(Child of parent doc)"]
|
||||||
|
else:
|
||||||
|
samples = get_sample_records(session, doctype)
|
||||||
|
if not samples:
|
||||||
|
samples = ["(No records)"]
|
||||||
|
|
||||||
|
# Format samples
|
||||||
|
sample_str = ", ".join(str(s) for s in samples[:2])
|
||||||
|
if len(sample_str) > 40:
|
||||||
|
sample_str = sample_str[:37] + "..."
|
||||||
|
|
||||||
|
# Format endpoints
|
||||||
|
doctype_url = urllib.parse.quote(doctype)
|
||||||
|
if issingle:
|
||||||
|
endpoints = f"`GET /api/resource/{doctype_url}/{doctype_url}`"
|
||||||
|
else:
|
||||||
|
endpoints = f"`/api/resource/{doctype_url}`"
|
||||||
|
|
||||||
|
doc.append(f"| {doctype} | {dtype} | {sample_str} | {endpoints} |")
|
||||||
|
|
||||||
|
total_processed += 1
|
||||||
|
if total_processed % 10 == 0:
|
||||||
|
print(f" Processed {total_processed} DocTypes...")
|
||||||
|
|
||||||
|
doc.append("")
|
||||||
|
|
||||||
|
print(f"\nProcessed {total_processed} DocTypes total")
|
||||||
|
|
||||||
|
# Common Query Parameters
|
||||||
|
doc.append("## Common Query Parameters")
|
||||||
|
doc.append("")
|
||||||
|
doc.append("### For List Endpoints")
|
||||||
|
doc.append("")
|
||||||
|
doc.append("| Parameter | Description | Example |")
|
||||||
|
doc.append("|-----------|-------------|---------|")
|
||||||
|
doc.append("| `fields` | Select specific fields | `fields=[\"name\",\"status\"]` |")
|
||||||
|
doc.append("| `filters` | Filter results | `filters=[[\"status\",\"=\",\"Active\"]]` |")
|
||||||
|
doc.append("| `limit_start` | Pagination offset | `limit_start=0` |")
|
||||||
|
doc.append("| `limit_page_length` | Page size | `limit_page_length=20` |")
|
||||||
|
doc.append("| `order_by` | Sort results | `order_by=modified desc` |")
|
||||||
|
doc.append("")
|
||||||
|
|
||||||
|
# Examples section
|
||||||
|
doc.append("## Examples")
|
||||||
|
doc.append("")
|
||||||
|
doc.append("### Get list with filters")
|
||||||
|
doc.append("```bash")
|
||||||
|
doc.append("curl -b cookies.txt \\")
|
||||||
|
doc.append(" \"http://localhost:8080/api/resource/Item?filters=[[\\\"item_group\\\",\\\"=\\\",\\\"Products\\\"]]&fields=[\\\"item_code\\\",\\\"item_name\\\"]\"")
|
||||||
|
doc.append("```")
|
||||||
|
doc.append("")
|
||||||
|
doc.append("### Get single document")
|
||||||
|
doc.append("```bash")
|
||||||
|
doc.append("curl -b cookies.txt \\")
|
||||||
|
doc.append(" \"http://localhost:8080/api/resource/User/Administrator\"")
|
||||||
|
doc.append("```")
|
||||||
|
doc.append("")
|
||||||
|
doc.append("### Create new document")
|
||||||
|
doc.append("```bash")
|
||||||
|
doc.append("curl -b cookies.txt -X POST \\")
|
||||||
|
doc.append(" -H \"Content-Type: application/json\" \\")
|
||||||
|
doc.append(" -d '{\"doctype\":\"Item\",\"item_code\":\"TEST-001\",\"item_name\":\"Test Item\",\"item_group\":\"Products\",\"stock_uom\":\"Nos\"}' \\")
|
||||||
|
doc.append(" \"http://localhost:8080/api/resource/Item\"")
|
||||||
|
doc.append("```")
|
||||||
|
doc.append("")
|
||||||
|
doc.append("### Update document")
|
||||||
|
doc.append("```bash")
|
||||||
|
doc.append("curl -b cookies.txt -X PUT \\")
|
||||||
|
doc.append(" -H \"Content-Type: application/json\" \\")
|
||||||
|
doc.append(" -d '{\"item_name\":\"Updated Test Item\"}' \\")
|
||||||
|
doc.append(" \"http://localhost:8080/api/resource/Item/TEST-001\"")
|
||||||
|
doc.append("```")
|
||||||
|
doc.append("")
|
||||||
|
doc.append("### Delete document")
|
||||||
|
doc.append("```bash")
|
||||||
|
doc.append("curl -b cookies.txt -X DELETE \\")
|
||||||
|
doc.append(" \"http://localhost:8080/api/resource/Item/TEST-001\"")
|
||||||
|
doc.append("```")
|
||||||
|
doc.append("")
|
||||||
|
|
||||||
|
# Special Endpoints
|
||||||
|
doc.append("## Special Endpoints")
|
||||||
|
doc.append("")
|
||||||
|
doc.append("### Authentication")
|
||||||
|
doc.append("- `POST /api/method/login` - Login")
|
||||||
|
doc.append("- `POST /api/method/logout` - Logout")
|
||||||
|
doc.append("")
|
||||||
|
doc.append("### File Operations")
|
||||||
|
doc.append("- `POST /api/method/upload_file` - Upload files")
|
||||||
|
doc.append("- `GET /api/method/download_file` - Download files")
|
||||||
|
doc.append("")
|
||||||
|
doc.append("### Reports")
|
||||||
|
doc.append("- `GET /api/method/frappe.desk.query_report.run` - Run reports")
|
||||||
|
doc.append("")
|
||||||
|
|
||||||
|
# DocType Categories
|
||||||
|
doc.append("## DocType Categories")
|
||||||
|
doc.append("")
|
||||||
|
doc.append("### Single DocTypes")
|
||||||
|
doc.append("These DocTypes have only one record (singleton pattern):")
|
||||||
|
doc.append("")
|
||||||
|
single_docs = [d.get("name") for d in doctypes if d.get("issingle")]
|
||||||
|
for doc_name in sorted(single_docs)[:20]: # Show first 20
|
||||||
|
doc.append(f"- {doc_name}")
|
||||||
|
if len(single_docs) > 20:
|
||||||
|
doc.append(f"- ... and {len(single_docs) - 20} more")
|
||||||
|
doc.append("")
|
||||||
|
|
||||||
|
doc.append("### Child Tables")
|
||||||
|
doc.append("These DocTypes are child tables and cannot be accessed directly:")
|
||||||
|
doc.append("")
|
||||||
|
child_docs = [d.get("name") for d in doctypes if d.get("istable")]
|
||||||
|
for doc_name in sorted(child_docs)[:20]: # Show first 20
|
||||||
|
doc.append(f"- {doc_name}")
|
||||||
|
if len(child_docs) > 20:
|
||||||
|
doc.append(f"- ... and {len(child_docs) - 20} more")
|
||||||
|
doc.append("")
|
||||||
|
|
||||||
|
doc.append("### Submittable DocTypes")
|
||||||
|
doc.append("These DocTypes support document submission workflow:")
|
||||||
|
doc.append("")
|
||||||
|
submit_docs = [d.get("name") for d in doctypes if d.get("is_submittable")]
|
||||||
|
for doc_name in sorted(submit_docs)[:20]: # Show first 20
|
||||||
|
doc.append(f"- {doc_name}")
|
||||||
|
if len(submit_docs) > 20:
|
||||||
|
doc.append(f"- ... and {len(submit_docs) - 20} more")
|
||||||
|
doc.append("")
|
||||||
|
|
||||||
|
# Notes
|
||||||
|
doc.append("## Important Notes")
|
||||||
|
doc.append("")
|
||||||
|
doc.append("1. **URL Encoding**: DocType names with spaces must be URL encoded (e.g., \"Sales Order\" → \"Sales%20Order\")")
|
||||||
|
doc.append("2. **Permissions**: Access to DocTypes depends on user permissions")
|
||||||
|
doc.append("3. **Rate Limiting**: Default rate limit is 60 requests per minute")
|
||||||
|
doc.append("4. **Single DocTypes**: Use the DocType name as both the resource and document name")
|
||||||
|
doc.append("5. **Child Tables**: Cannot be accessed directly, only through their parent document")
|
||||||
|
doc.append("6. **Submittable Documents**: Support additional states (Draft, Submitted, Cancelled)")
|
||||||
|
doc.append("")
|
||||||
|
|
||||||
|
return "\n".join(doc)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("=" * 50)
|
||||||
|
print("ERPNext API Documentation Generator")
|
||||||
|
print("=" * 50)
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Login
|
||||||
|
session = login()
|
||||||
|
if not session:
|
||||||
|
print("Failed to login!")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Generate documentation
|
||||||
|
documentation = generate_documentation(session)
|
||||||
|
|
||||||
|
# Save to file
|
||||||
|
output_file = "API_ENDPOINTS.md"
|
||||||
|
with open(output_file, "w") as f:
|
||||||
|
f.write(documentation)
|
||||||
|
|
||||||
|
print()
|
||||||
|
print("=" * 50)
|
||||||
|
print(f"✓ Documentation saved to: {output_file}")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
44
test_api.sh
Executable file
44
test_api.sh
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# ERPNext API Test Script
|
||||||
|
# This script demonstrates how to access ERPNext APIs
|
||||||
|
|
||||||
|
API_URL="http://localhost:8080"
|
||||||
|
USERNAME="Administrator"
|
||||||
|
PASSWORD="LocalDev123!"
|
||||||
|
|
||||||
|
echo "======================================"
|
||||||
|
echo "ERPNext API Test Script"
|
||||||
|
echo "======================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 1. Login and save cookies
|
||||||
|
echo "1. Logging in..."
|
||||||
|
curl -s -c cookies.txt -X POST \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{\"usr\":\"$USERNAME\",\"pwd\":\"$PASSWORD\"}" \
|
||||||
|
$API_URL/api/method/login | jq '.'
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "2. Getting list of DocTypes (first 5)..."
|
||||||
|
curl -s -b cookies.txt "$API_URL/api/resource/DocType?limit_page_length=5" | jq '.data[].name'
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "3. Getting list of Users..."
|
||||||
|
curl -s -b cookies.txt "$API_URL/api/resource/User?fields=\[\"name\",\"full_name\",\"enabled\"\]&limit_page_length=3" | jq '.'
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "4. Getting system settings..."
|
||||||
|
curl -s -b cookies.txt "$API_URL/api/resource/System%20Settings/System%20Settings" | jq '{country: .data.country, timezone: .data.time_zone}'
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "5. Getting Company list..."
|
||||||
|
curl -s -b cookies.txt "$API_URL/api/resource/Company" | jq '.'
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "======================================"
|
||||||
|
echo "API test complete!"
|
||||||
|
echo "======================================"
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
rm -f cookies.txt
|
||||||
Loading…
Reference in New Issue
Block a user