mcpField
F
frappe-core-api

frappe-core-api

github.com/impertio-studio開発198124 回インストール30 週間前に更新
リポジトリ

frappe-core-api について

Frappe 開発者向けに、REST、RPC、Webhook の連携パターンをまとめたガイドです。API 認証、ドキュメント CRUD、カスタムメソッド、イベント通知に加え、ページ分割や権限確認、署名検証などの安全対策も扱います。

主な機能

  1. 01REST ドキュメント CRUD とバージョン別エンドポイント
  2. 02Token、OAuth 2.0、セッション認証
  3. 03RPC によるカスタムメソッド呼び出し
  4. 04Webhook イベントと署名検証
  5. 05ページ分割、権限、入力検証の指針

活用シーン

  1. 01外部クライアントから Frappe ドキュメントを読み書き
  2. 02連携用 API 認証の設定
  3. 03RPC によるカスタムサーバーロジックの呼び出し
  4. 04ドキュメント変更 Webhook の受信と検証

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/impertio-studio/frappe_claude_skill_package --skill frappe-core-api

インストール後、Claude Code で/frappe-core-apiを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
anti-patterns.md
authentication-methods.md
examples.md
rest-api-reference.md
rpc-api-reference.md
webhooks-reference.md

詳細

Frappe API パターン

Frappe との REST、RPC、Webhook 連携における決定論的なパターンです。


判断フローチャート

What do you need?
├── CRUD on documents (external client)
│   ├── v14: REST /api/resource/{doctype}
│   └── v15+: REST /api/v2/document/{doctype} (new) or /api/resource/ (still works)
│
├── Call custom server logic (external client)
│   └── RPC: POST /api/method/{dotted.path.to.function}
│
├── Notify external systems on document events
│   └── Webhooks (configured in UI or via DocType)
│
├── Client-side calls (JavaScript in Frappe desk)
│   ├── frappe.xcall() — async/await (RECOMMENDED)
│   └── frappe.call() — callback/promise pattern
│
└── Authentication method?
    ├── Server-to-server integration → Token Auth (RECOMMENDED)
    ├── Third-party app / mobile → OAuth 2.0
    ├── Browser session (short-lived) → Session/Cookie Auth
    └── Quick scripting / testing → Token Auth

認証方法

トークン認証(連携には推奨)
headers = {
    'Authorization': 'token api_key:api_secret',
    'Accept': 'application/json',
    'Content-Type': 'application/json'
}

キーを生成するには、「User > Settings > API Access > Generate Keys」の順に選択します。API シークレットは表示されるのが一度だけなので、必ずすぐに保存してください。

Basic 認証(代替のトークン形式)
import base64
credentials = base64.b64encode(b'api_key:api_secret').decode()
headers = {'Authorization': f'Basic {credentials}'}
OAuth 2.0(サードパーティアプリ)
# Step 1: Authorization redirect
GET /api/method/frappe.integrations.oauth2.authorize
    ?client_id={id}&response_type=code&scope=openid all
    &redirect_uri={uri}&state={random}

# Step 2: Exchange code for token
POST /api/method/frappe.integrations.oauth2.get_token
    grant_type=authorization_code&code={code}
    &redirect_uri={uri}&client_id={id}

# Step 3: Use bearer token
Authorization: Bearer {access_token}

# Refresh token
POST /api/method/frappe.integrations.oauth2.get_token
    grant_type=refresh_token&refresh_token={token}&client_id={id}
セッション/Cookie 認証
session = requests.Session()
session.post(url + '/api/method/login', json={'usr': 'email', 'pwd': 'pass'})
# Subsequent requests use session cookie automatically

セッション Cookie の有効期限は約 3 日です。長時間実行する連携には絶対に使用しないでください。


REST API:リソースの CRUD

エンドポイント
操作メソッドv14 エンドポイントv15 以降の v2 エンドポイント
一覧GET/api/resource/{doctype}/api/v2/document/{doctype}
作成POST/api/resource/{doctype}/api/v2/document/{doctype}
読み取りGET/api/resource/{doctype}/{name}/api/v2/document/{doctype}/{name}
更新PUT/api/resource/{doctype}/{name}PATCH /api/v2/document/{doctype}/{name}
削除DELETE/api/resource/{doctype}/{name}DELETE /api/v2/document/{doctype}/{name}
コピー——GET /api/v2/document/{doctype}/{name}/copy [v15+]
Doc メソッド——POST /api/v2/document/{doctype}/{name}/method/{method} [v15+]

必ず Accept: application/json ヘッダーを含めてください。含めない場合、Frappe が HTML を返すことがあります。

一覧パラメーター
パラメーター型説明デフォルト
fieldsJSON 配列返すフィールド["name"]
filtersJSON 配列AND 条件なし
or_filtersJSON 配列OR 条件なし
order_by文字列並べ替え式modified desc
limit_startintページネーションの開始位置0
limit_page_lengthintページサイズ20
limitintlimit_page_length の別名 [v15+]—
debugboolレスポンスに SQL を表示false
フィルター演算子
filters = [["status", "=", "Open"]]
filters = [["amount", ">", 1000]]
filters = [["status", "in", ["Open", "Pending"]]]
filters = [["date", "between", ["2024-01-01", "2024-12-31"]]]
filters = [["reference", "is", "set"]]       # NOT NULL
filters = [["reference", "is", "not set"]]   # IS NULL
filters = [["name", "like", "%INV%"]]
filters = [["status", "not in", ["Cancelled"]]]

演算子の全一覧:=, !=, >, <, >=, <=, like, not like, in, not in, is, between。

ページネーションのパターン
import json, requests

def get_all_records(doctype, headers, base_url, page_size=100):
    all_data, offset = [], 0
    while True:
        params = {
            'fields': json.dumps(["name", "modified"]),
            'limit_start': offset,
            'limit_page_length': page_size
        }
        resp = requests.get(f'{base_url}/api/resource/{doctype}',
                            params=params, headers=headers)
        data = resp.json().get('data', [])
        if not data:
            break
        all_data.extend(data)
        if len(data) < page_size:
            break
        offset += page_size
    return all_data
子テーブルを含めて作成
requests.post(f'{base_url}/api/resource/Sales Order', json={
    "customer": "CUST-001",
    "items": [
        {"item_code": "ITEM-001", "qty": 5, "rate": 100},
        {"item_code": "ITEM-002", "qty": 2, "rate": 250}
    ]
}, headers=headers)
更新(部分更新)
# Only specified fields are changed
requests.put(f'{base_url}/api/resource/Customer/CUST-001',
             json={"customer_group": "Premium"}, headers=headers)
ファイルのアップロード
requests.post(f'{base_url}/api/method/upload_file',
    files={'file': ('doc.pdf', open('doc.pdf', 'rb'), 'application/pdf')},
    data={'doctype': 'Customer', 'docname': 'CUST-001', 'is_private': 1},
    headers={'Authorization': 'token api_key:api_secret'})
# NOTE: Do NOT set Content-Type header — requests sets multipart boundary automatically

RPC API:カスタムメソッド

サーバーサイドエンドポイント
@frappe.whitelist()
def get_balance(customer):
    """GET /api/method/myapp.api.get_balance?customer=CUST-001"""
    return frappe.db.get_value("Customer", customer, "outstanding_amount")

@frappe.whitelist(methods=["POST"])
def create_payment(customer, amount):
    """POST /api/method/myapp.api.create_payment"""
    if not frappe.has_permission("Payment Entry", "create"):
        frappe.throw(_("Not permitted"), frappe.PermissionError)
    pe = frappe.new_doc("Payment Entry")
    pe.party_type = "Customer"
    pe.party = customer
    pe.paid_amount = float(amount)
    pe.insert()
    return pe.name

@frappe.whitelist(allow_guest=True)
def public_status():
    """No authentication required."""
    return {"status": "ok"}
デコレーターのオプション
オプション効果バージョン
allow_guest=True認証不要すべて
methods=["POST"]HTTP メソッドを制限[v14+]
xss_safe=Trueレスポンスの XSS エスケープを省略すべて
レスポンス構造
// RPC success
{"message": "return_value"}

// REST success
{"data": {...}}

// Error
{"exc_type": "ValidationError", "_server_messages": "[{\"message\": \"...\"}]"}
クライアント側からの呼び出し(JavaScript)
// RECOMMENDED: async/await with frappe.xcall
const result = await frappe.xcall('myapp.api.get_balance', {
    customer: 'CUST-001'
});

// Alternative: frappe.call with promise
frappe.call({
    method: 'myapp.api.get_balance',
    args: {customer: 'CUST-001'},
    freeze: true,
    freeze_message: __('Loading...')
}).then(r => console.log(r.message));

// Document method (frm.call)
frm.call('get_linked_doc', {throw_if_missing: true})
    .then(r => console.log(r.message));
標準の frappe.client メソッド
メソッドエンドポイント用途
frappe.client.get_valuePOST単一フィールドの値を取得
frappe.client.get_listPOSTフィルターを指定して一覧を取得
frappe.client.getPOSTドキュメント全体を取得
frappe.client.insertPOSTドキュメントを作成
frappe.client.savePOSTドキュメントを更新
frappe.client.deletePOSTドキュメントを削除
frappe.client.submitPOSTドキュメントを送信
frappe.client.cancelPOSTドキュメントを取り消し
frappe.client.get_countPOSTドキュメント数を取得

Webhook

UI の Webhook DocType で設定します。イベント:

イベント発生条件
after_insert新しいドキュメントの作成後
on_update保存のたび
on_submit送信後(docstatus=1)
on_cancel取り消し後(docstatus=2)
on_trash削除前
on_update_after_submit修正後
on_change変更のたび

セキュリティ:必ず Webhook Secret を設定してください。Frappe は、ペイロードの HMAC-SHA256 を Base64 エンコードした値を含む X-Frappe-Webhook-Signature ヘッダーを追加します。受信側で検証してください。

条件:Jinja2 を使用します — {{ doc.grand_total > 10000 }}。

ハンドラーの完全な例については、references/webhooks-reference.md を参照してください。

HTTP ステータスコード

コード意味一般的な原因
200成功—
400不正なリクエスト検証エラー
401認証されていません認証情報がない、または無効
403禁止されています操作の権限がありません
404見つかりませんドキュメントが存在しません
417期待に応えられませんでしたサーバー例外(frappe.throw)
429レート制限されていますリクエストが多すぎます
500サーバーエラー未処理の例外

重要なルール

  1. API リクエストには必ず Accept: application/json ヘッダーを含めてください
  2. @frappe.whitelist() メソッドには必ず権限チェックを追加してください
  3. ホワイトリスト登録されたメソッドでは、入力を必ず検証してサニタイズしてください
  4. 必ずパラメーター化クエリーを使用してください。SQL に文字列を埋め込むことは絶対に避けてください
  5. 外部への requests 呼び出しでは必ず timeout=30 を使用してください
  6. 認証情報は必ず frappe.conf または環境変数に保存してください。ハードコードは絶対に避けてください
  7. Webhook の署名は HMAC-SHA256 で必ず検証してください
  8. リストのレスポンスは必ずページネーションしてください。件数に上限のない結果セットを返すことは絶対に避けてください
  9. 状態を変更するエンドポイントで allow_guest=True を使用することは絶対に避けてください
  10. 認証情報や機密データをログに記録することは絶対に避けてください
  11. 連携には Administrator の API キーを使用することは絶対に避けてください。専用の API ユーザーを作成してください

アンチパターン

してはいけないこと代わりにすること
ホワイトリストで権限チェックをしないアクションの前に frappe.has_permission() を呼び出す
frappe.db.sql(f"...{user_input}")パラメーター化された %s クエリー
allow_guest=True と状態変更の組み合わせ認証を必須にする
上限なしですべてのレコードを返すlimit_page_length でページネーションする
API 認証情報をハードコードするfrappe.conf.get("api_key")
負荷の高い処理を同期的に行う長時間のタスクには frappe.enqueue() を使用する
外部呼び出しにタイムアウトを設定しないrequests.get(url, timeout=30)
レスポンス形式に一貫性がない必ず {"status": "...", "data": ...} を返す

バージョンの違い

機能v14v15v16
/api/resource/(v1)はいはいはい
/api/v2/document/(v2)いいえはいはい
/api/v2/doctype/{dt}/metaいいえはいはい
/api/v2/doctype/{dt}/countいいえはいはい
limit エイリアスパラメーターいいえはいはい
OAuth2 の PKCE一部対応はいはい
Server Script のレート制限いいえはいはい
v2 URL 経由の Doc メソッドいいえはいはい

参照ファイル

ファイル内容
authentication-methods.mdトークン、セッション、OAuth2 のコード例
rest-api-reference.mdフィルターとページネーションを含む REST CRUD の全般
rpc-api-reference.mdホワイトリスト登録されたメソッド、frappe.call、frappe.xcall
webhooks-reference.mdWebhook の設定、セキュリティ、ハンドラーの例
anti-patterns.mdよくあるミスと修正方法
examples.mdPython/JS/cURL のクライアント実装

関連スキル

  • frappe-core-permissions — API エンドポイントの権限システム
  • frappe-core-database — API メソッドの背後にあるデータベースクエリー
  • frappe-syntax-hooks — Webhook のフック設定
  • frappe-syntax-controllers — API 経由で呼び出すコントローラーメソッド

Frappe のドキュメントに基づき検証済み 2026-03-20 | Frappe v14/v15/v16

コメント