mcpField
F
frappe-api-development

frappe-api-development

github.com/lubusin開発69248 回インストール12 週間前に更新
リポジトリ

frappe-api-development について

Frappe 開発者向けの API 開発スキルです。REST、RPC、Webhook の方式に加え、認証、権限、入力検証を扱い、外部連携やフロントエンドへの業務ロジック公開に役立ちます。

主な機能

  1. 01REST、RPC、Webhook 方式の選択
  2. 02カスタム RPC エンドポイントの作成
  3. 03トークンやセッション認証の設定
  4. 04権限確認と入力検証
  5. 05長時間処理のバックグラウンド実行

活用シーン

  1. 01DocType の CRUD エンドポイント提供
  2. 02フロントエンドへの独自業務操作の公開
  3. 03外部システムからのコールバック受信
  4. 04長時間のエクスポート実行と状態確認

インストール

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

$npx skills add https://github.com/lubusin/frappe-skills --skill frappe-api-development

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

同梱ファイル

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

references/
authentication.md
oauth.md
permissions.md
python-api.md
rate-limiting.md
rest-api.md
server-scripts.md
webhooks.md

詳細

Frappe API 開発

Frappe の REST および RPC パターンを使用して、安全で適切に設計された API を構築します。

使用する場面

  • カスタム RPC エンドポイント(@frappe.whitelist)の作成
  • REST API 連携の構築
  • 外部システム向けの Webhook の実装
  • API 認証(トークン、OAuth)の設定
  • フロントエンドへのビジネスロジックの公開

必要な入力

  • API の目的(CRUD、アクション、連携)
  • 認証要件(公開、ユーザー、API キー)
  • エンドポイントごとの権限要件
  • リクエスト/レスポンス形式の要件

手順

0) API パターンを選択する
必要な処理パターン
DocType の CRUD組み込みの REST API を使用
カスタムアクション@frappe.whitelist を使用した RPC
外部からのコールバックWebhook DocType
バッチ処理バックグラウンドジョブ+ステータスエンドポイント
1) 組み込みの REST API(DocType の CRUD)

Frappe は、すべての DocType に対して自動的に REST エンドポイントを提供します。

# Create
POST /api/resource/Customer
{"customer_name": "Acme Corp"}

# Read
GET /api/resource/Customer/CUST-001

# Update
PUT /api/resource/Customer/CUST-001
{"customer_name": "Acme Corporation"}

# Delete
DELETE /api/resource/Customer/CUST-001

# List with filters
GET /api/resource/Customer?filters=[["status","=","Active"]]
2) カスタム RPC エンドポイント

アプリ内にホワイトリスト登録したメソッドを作成します。

# my_app/api.py
import frappe

@frappe.whitelist()
def process_order(order_id, action):
    """Process an order with the given action."""
    # Always verify permissions
    doc = frappe.get_doc("Sales Order", order_id)
    if not frappe.has_permission("Sales Order", "write", doc):
        frappe.throw("Not permitted", frappe.PermissionError)
    
    # Business logic
    if action == "approve":
        doc.status = "Approved"
        doc.save()
    
    return {"status": "success", "order": doc.name}

@frappe.whitelist(allow_guest=True)
def public_endpoint():
    """Public endpoint - no auth required."""
    return {"message": "Hello, World!"}

次の方法で呼び出します。

POST /api/method/my_app.api.process_order
{"order_id": "SO-001", "action": "approve"}
3) 認証を実装する

API キー+シークレット(連携に推奨):

# Header format
Authorization: token api_key:api_secret

ベアラートークン:

Authorization: Bearer <token>

セッション(ログイン済みユーザー向け): Cookie により自動的に認証されます。

4) 権限チェック

RPC メソッドでは必ず権限をチェックしてください。

@frappe.whitelist()
def sensitive_action(docname):
    doc = frappe.get_doc("My DocType", docname)
    
    # Check document-level permission
    if not frappe.has_permission("My DocType", "write", doc):
        frappe.throw("Not permitted", frappe.PermissionError)
    
    # Check role-based permission
    if "Manager" not in frappe.get_roles():
        frappe.throw("Manager role required")
    
    # Proceed with action
    ...
5) 入力の検証
@frappe.whitelist()
def create_item(name, qty, price):
    # Validate required fields
    if not name:
        frappe.throw("Name is required")
    
    # Validate types
    qty = frappe.utils.cint(qty)
    price = frappe.utils.flt(price)
    
    # Validate ranges
    if qty <= 0:
        frappe.throw("Quantity must be positive")
    
    # Proceed
    ...
6) レスポンス形式

成功レスポンス:

return {
    "status": "success",
    "data": {...}
}

エラー処理:

# User-facing error
frappe.throw("Validation failed", title="Error")

# Permission error
frappe.throw("Not allowed", frappe.PermissionError)

# Standard exceptions become {"exc_type": "...", "exc": "..."}
7) 時間のかかる処理にはバックグラウンドジョブを使用する
@frappe.whitelist()
def start_export(filters):
    job = frappe.enqueue(
        "my_app.jobs.run_export",
        filters=filters,
        queue="long",
        timeout=600
    )
    return {"job_id": job.id}

@frappe.whitelist()
def check_job_status(job_id):
    from frappe.utils.background_jobs import get_job
    job = get_job(job_id)
    return {"status": job.get_status()}

検証

  • 有効なリクエストに対してエンドポイントが正しく応答する
  • 権限のないアクセスに対して権限エラーが返される
  • 入力検証で無効なデータが拒否される
  • エラーレスポンスが構造化され、役立つ内容になっている
  • 実行する:bench --site <site> console → エンドポイントを手動でテストする

問題発生時の対処/デバッグ

  • メソッドが見つからない:URL 内のモジュールパスが Python のパスと一致しているか確認します
  • 権限が拒否される:@frappe.whitelist() デコレーターとユーザー権限を確認します
  • CSRF エラー:API 呼び出しに適切な認証ヘッダーを使用します
  • 500 エラー:エラーログを確認します:bench --site <site> show-log

エスカレーション

参考資料

ガードレール

  • 入力を必ず検証する:クライアントのデータを決して信用せず、サーバー側で型、長さ、形式を検証します
  • 権限コールバックを使用する:ホワイトリスト登録したメソッド内で frappe.has_permission() を明示的に確認します
  • ユーザー入力をサニタイズする:SQL には frappe.db.escape() を使用し、eval() や動的コード実行は避けます
  • レート制限を処理する:不正利用を防ぐため、公開 API にレート制限を実装します
  • 構造化されたエラーを返す:適切な HTTP ステータスコードとともに frappe.throw() を使用します

よくある間違い

間違い発生する問題修正方法
@frappe.whitelist() がないメソッドが「Method not found」エラーを返すAPI 経由でメソッドを公開するため、デコレーターを追加する
更新処理に GET を使用するREST の慣例に反し、CSRF の問題が発生するデータの変更には POST/PUT/DELETE を使用する
エラーを処理しない500 エラーでスタックトレースが露出するtry/except で囲み、frappe.throw() を使用する
機密データを公開するセキュリティ侵害が発生するレスポンスのフィールドを絞り込み、権限を確認する
allow_guest=True がない公開エンドポイントが 403 を返す認証なしのアクセスを許可するには @frappe.whitelist(allow_guest=True) を追加する
クエリで SQL インジェクションが発生するデータベースが侵害されるQuery Builder または frappe.db.escape() を使用する

コメント