netbox-api-integration について
NetBox を統合する開発者向けのスキルで、REST/GraphQL API の認証、クエリ、バルク操作、性能改善、データモデリングを扱います。バージョンごとの API の違いも説明します。
主な機能
- 01REST/GraphQL のクエリパターン
- 02トークン認証とバージョン上の注意
- 03ページネーションとバルク書き込み
- 04フィルター、同時実行、性能改善
- 05NetBox オブジェクトの依存関係とモデリング
活用シーン
- 01NetBox API 統合コードの作成
- 02大規模データセットのページング
- 03オブジェクトの一括作成や更新
MCP 対応
設定済みの NetBox MCP server または NetBox Platform MCP を使い、ライブインスタンスでフィールド、フィルター、オブジェクト状態を確認する方法を説明します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ netboxlabs/ skills --skill netbox-api-integrationインストール後、Claude Code で/netbox-api-integrationを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/authentication.mdbranching-patterns.mddata-modeling.mddiode-integration.mdgraphql-patterns.mdperformance.mdrest-api-patterns.md詳細
NetBox API 連携
NetBox REST API と GraphQL API を連携するためのパターンと実践方法を紹介します。認証、クエリ、バルク操作、パフォーマンスの最適化、データモデリング、連携ツールについて説明します。
対象: NetBox 4.5~4.7(現行バージョン:4.7.3)。v2 トークンには 4.5 以降が必要です。REST のカーソルページネーション、ETag/If-Match、add_tags/remove_tags には 4.6 以降が必要です。?background=true、オブジェクト単位のバルクエラー、{value, label} 形式の選択型カスタムフィールドは 4.7 以降で利用できます。バージョンに関する注意事項を参照してください。
範囲: API 連携のみです。プラグイン開発、カスタムスクリプト、NetBox の管理は対象外です。
NetBox API に関する知識が古くなっている可能性があります。 ページネーションの動作、フィルター式、トークン形式、GraphQL の機能はリリース間で変更されます。API の詳細を確認する際は、事前学習済みの知識よりも情報の取得を優先してください。
情報の取得元
| 情報源 | URL/方法 | 用途 |
|---|---|---|
| NetBox REST API ドキュメント | https://netboxlabs.com/docs/netbox/integrations/rest-api/ | エンドポイント、フィルタリング、ページネーション |
| NetBox GraphQL ドキュメント | https://netboxlabs.com/docs/netbox/integrations/graphql-api/ | クエリ構文、スキーマ |
| pynetbox リポジトリ | https://github.com/netbox-community/pynetbox | SDK メソッド、変更履歴 |
| NetBox MCP サーバー | 設定されている場合は、稼働中のインスタンスにクエリを実行してオブジェクトスキーマと現在の状態を確認 | フィールド名、利用可能なフィルター、オブジェクトの存在 |
| NetBox Platform MCP | 設定されている場合は、稼働中の NetBox Cloud/Enterprise に対して CRUD 全般を検証 | エンドツーエンドの検証 |
最初に:接続を確認する
連携コードを書く前に、NetBox インスタンスに接続でき、トークンが有効であることを確認してください。
curl -s -H "Authorization: Bearer $NETBOX_TOKEN" "$NETBOX_URL/api/status/" | python -m json.tool
netbox-version を含む JSON レスポンスが表示されます。403 が返る場合、トークンに必要な権限がありません。接続が拒否される場合は、URL を確認してください。
認証
NetBox 4.5 以降では v2 トークンを使用してください。v1 トークンは4.6 で非推奨となり、5.0 で削除されます。
# v2 token (recommended)
headers = {"Authorization": "Bearer nbt_abc123.xxxxxxxxxxxxxxxx"}
# v1 token (legacy — deprecated 4.6, removed 5.0; migrate before 5.0)
headers = {"Authorization": "Token 0123456789abcdef01234567"}
v2 トークンを使用するには、NetBox サーバーの設定で API_TOKEN_PEPPERS が必要です。トークンを自動作成する場合は、プロビジョニングエンドポイント(POST /api/users/tokens/provision/)を使用してください。作成/プロビジョニングレスポンスの token フィールドに平文が含まれます(key は公開識別子のみです)。平文は一度だけ返されるため(4.6.1 以降)、すぐに取得してください。それ以降はハッシュのみが保存されます。
NetBox 4.7 以降: 作成時に
tokenは読み取り専用です。サーバーが常に平文を生成し、クライアントから指定された値は無視されます。トークンを?background=trueで作成しないでください。4.7.0/4.7.1 では平文がジョブ結果に記録され(core.view_job権限を持つすべてのユーザーが読み取り可能)、4.7.2 では 400 エラーで拒否されます。4.7.2 以降を実行し、この方法で作成されたトークンはすべてローテーションしてください。POST /api/extras/scripts/<id>/によるカスタムスクリプトの実行には、書き込みが有効なトークンが必要になりました。
トークンの移行、IP 制限、プロビジョニングの詳細については、references/authentication.mdを参照してください。
REST API の基本
常にページネーションを使用する
def get_all(api_url, endpoint, headers, limit=100):
results, url = [], f"{api_url}/{endpoint}/?limit={limit}"
while url:
data = requests.get(url, headers=headers).json()
results.extend(data["results"])
url = data.get("next")
return results
NetBox 4.6 以降 — カーソルページネーション。 大規模なデータセットでは、
offsetの代わりに?start=<pk>&limit=<n>を指定してください。PK の昇順で、id >= startのオブジェクトが返されます。次のstartには最後の結果のidに 1 を加えた値を設定し、nextが null になるまで繰り返してください。注意点:startとoffsetを併用すると 400 が返されます。カーソルモードではcountは常にnullです。previousも常にnullで、前方向にしか進めません。合計のcountや前のページへの移動が必要な場合は、オフセットページネーションを使用してください。
PUT ではなく PATCH を使用する
PATCH は指定したフィールドのみを更新します。PUT はオブジェクト全体を置き換えるため、省略したフィールドがクリアされる場合があります。
並行処理とタグ(NetBox 4.6+)
- 楽観的同時実行制御(ETag / If-Match)。 詳細ビューのレスポンス(単一オブジェクトに対する GET/POST/PATCH/PUT)では、弱い
ETagヘッダーが返されます。後続の PATCH/PUT でIf-Match: <etag>を送り返すと、その間にオブジェクトが変更されていた場合、サーバーは 412 Precondition Failed を返し、現在の ETag を返します。If-Match: *はオブジェクトの存在のみを確認します。ヘッダーを省略すると、最終書き込み優先の動作が維持されます。複数の書き込み元を持つインテグレーションで、更新の消失を防ぐために使用してください。 - タグの部分編集(
add_tags/remove_tags)。tagsセット全体を置き換えずに、特定のタグを追加または削除する書き込み専用フィールドです。複数のクライアントがそれぞれタグの一部を管理している場合でも、安全に並行処理できます。制約:同じリクエストでtagsと併用できません。remove_tagsは更新時のみ使用でき(作成時は使用できません)、同じタグを両方のリストに含めることはできません。
一括操作ではリストエンドポイントを使用する
一括操作専用のエンドポイントはありません。リストエンドポイントに JSON 配列を POST/PATCH/DELETE します。一括操作はすべて アトミック(すべて成功するか、すべて失敗するか)です。
# Bulk create
requests.post(f"{API_URL}/dcim/devices/", headers=headers, json=[device1, device2])
# Bulk update (each object must include "id")
requests.patch(f"{API_URL}/dcim/devices/", headers=headers, json=[{"id": 1, "status": "active"}])
# Bulk delete
requests.delete(f"{API_URL}/dcim/devices/", headers=headers, json=[{"id": 1}, {"id": 2}])
NetBox 4.7+:一括書き込みが失敗すると、
{"detail": "...", "errors": [...]}が返され、失敗したオブジェクトごとにエントリが含まれます。作成の場合は{"index": N, "errors": {...}}、更新/削除の場合は{"id": N, "errors": {...}}です。該当するオブジェクトだけを修正して再送信してください(バッチは引き続きロールバックされます)。大規模な一括書き込みをジョブとして実行するには、?background=trueを追加します。この場合、{"job": {"id", "url", "status"}}とともに 202 が返され、検証はワーカーで遅延実行されるため、job.urlをポーリングしてdata.status_codeを確認する必要があります。references/rest-api-patterns.mdを参照してください。
重要なパフォーマンス上のルール
- デバイス/VM のリストでは
config_contextを除外します。 4.5~4.6 ではリクエストごとにオブジェクト単位でレンダリングされるため、10~100 倍の高速化のために必ず?omit=config_context(4.5.2+。このバージョンでは?exclude=config_contextも同等です)を送信してください。4.7.0~4.7.2 では事前レンダリングされてキャッシュされ、常に読み込まれます。?fields=、?brief=True、?omit=config_contextはペイロードを小さくするだけです。4.7.3+ では、同じパラメーターによって DB のアノテーションとキャッシュ列の読み込みが再びスキップされるため、除外がパフォーマンスに影響します(4.6 ほどではありませんが、効果があります)。?exclude=はすべての 4.7.x で何も行いません。バージョンを問わず使える形式として?omit=config_contextを使用してください。 - ドロップダウンと参照リストには
?brief=Trueを使用します(レスポンスを約 90% 削減) - 特定のフィールドを選択するには
?fields=を使用します - 大規模な検索では
?q=フィルターを避け、name__ic=などの具体的なフィルターを使用します
フィルタリング
サーバー側のフィルタリングにはルックアップ式を使用します。
| 式 | 例 | 説明 |
|---|---|---|
__ic | name__ic=core | 部分一致(大文字と小文字を区別しない) |
__isw | name__isw=sw- | 前方一致 |
__gte/__lte | vid__gte=100 | 数値範囲 |
__isnull | primary_ip4__isnull=false | Null の確認 |
__n | status__n=offline | 不一致 |
cf_ prefix | cf_environment=production | カスタムフィールドフィルター |
フィルタリング式、フィールド選択、並べ替え、ネストされたシリアライザー、OPTIONS による検出、エラー処理など、REST API の完全なリファレンスについては、references/rest-api-patterns.mdを参照してください。
GraphQL の基本
すべてのリストクエリでページネーションを行う
query {
device_list(pagination: {limit: 100, offset: 0}) {
name
status
site { name }
}
}
ネストの各レベルでページネーションを行う
# Nested lists must also have limits
site_list(pagination: {limit: 10}) {
devices(pagination: {limit: 50}) {
interfaces(pagination: {limit: 100}) { name }
}
}
主なルール
- クエリオプティマイザーを使用してください — 本番環境では必須です。実際のケースでは、スコアが20,500から17に低下しました。
- 必要なフィールドのみをリクエストしてください — 過剰なデータ取得は避けてください
- 深さは3以下に抑え、5を超えないようにしてください
filters:パラメーターを使用してサーバー側でフィルタリングしてください- パフォーマンス向上のため、名前フィルターよりIDフィルターを使用してください(JOINを回避できます)
- 正確なスコアを得るため、本番データを使ってオプティマイザーを調整してください
NetBox 4.5+:深くネストしたフィルターパスの代わりに、ローカルフィルターフィールド(例:
interface_list上のsite)を使用してください。NetBox 4.5.2+:カーソルベースのページネーションがGAになりました。
pagination: {start: N, limit: M}を渡すと、id >= startのレコードが主キー順で返されます。次のページのstartには、最後のレコードのid+ 1を設定してください。(startを省略すると、オフセットページネーションにフォールバックします。)これにより、従来のfilters: {id__gte: N}を使う深いページネーションの回避策は置き換えられます。この回避策が必要なのは4.5.2より前のバージョンのみです。NetBox 4.7+:
custom_fields内の選択/複数選択の値は、RESTと同様に{value, label}オブジェクトとして解決されます。サービスフィルターはフラットなリスト値(port_mappings、protocol、port、port__gt/gte/lt/lte)であり、ServiceProtocolEnumのメンバーはTCP/UDP/SCTPです(ROLE_プレフィックスはありません)。references/graphql-patterns.mdを参照してください。
GraphQLのページネーションのデフォルト(RESTとは異なります):
paginationをまったく指定しない場合、一致するレコードがすべて返されます。limitを指定せずにpaginationを指定すると、Strawberry Djangoのデフォルトである100件が返されます(RESTのデフォルトは50件です)。pagination: {limit: 0}を指定すると、0件が返されます。RESTの?limit=0(すべて返す)とは逆です。MAX_PAGE_SIZE(デフォルトは1000)によってlimitの上限が設定されます。**NetBox 4.6.1+**では、サーバー側でGRAPHQL_MAX_QUERY_DEPTHも適用されるため、深すぎるクエリは遅くなるだけでなく、完全に拒否される場合があります。
GraphQLとRESTの使い分け
| ユースケース | 使用するもの |
|---|---|
| 単一オブジェクトのCRUD | REST |
| 一括作成/更新/削除 | REST(GraphQLは読み取り専用です) |
| 1回のリクエストで関連データを取得 | GraphQL |
| CI/CDスクリプト | REST |
| 柔軟なレポート作成 | GraphQL |
ページネーション戦略、深さの管理、ファンアウトの回避、複雑さの予算、クエリオプティマイザーなど、GraphQLの詳細についてはreferences/graphql-patterns.mdを参照してください。
パフォーマンス
最も効果の大きい最適化は次のとおりです。
| 最適化 | 効果 |
|---|---|
リストからconfig_contextを除外する(4.5.2+では?omit=config_context、?exclude=は4.5~4.6のみで動作し、4.7.xではすべて無視されます) | 4.5~4.6では10~100倍高速化。4.7.0~4.7.2ではペイロードのみ(キャッシュ済み)。4.7.3+ではDBアノテーションの再実行を回避 |
リストには?brief=Trueを使用する | レスポンスを約90%縮小 |
大規模環境では?q=を避ける | 桁違いに高速化 |
| 独立したリクエストを並列化する | 線形の高速化 |
| 汎用検索より具体的なフィルターを使用する | インデックスに最適化されたクエリ |
非同期ページネーション、キャッシュ戦略、リクエストの並列化パターン、インフラストラクチャに関する考慮事項については、references/performance.mdを参照してください。
データモデリング
依存関係の順序
オブジェクトは次の順序で作成する必要があります:Organization → Sites → DCIM Prerequisites → Racks → Devices → IPAM → Virtualization → Circuits → Connections。
デバイスを作成するには、先にそのdevice_type、role、siteが存在している必要があります。手動での順序付けを省略するには、Diodeを使用してください。
主な階層構造
- Site:Region → Site Group → Site → Location(再帰)→ Rack → Device
- IPAM:RIR → Aggregate → Prefix(階層構造)→ IP Address。VRFはPrefix/IPのスコープを設定します
自然キー、カスタムフィールド、タグ、テナント
- 数値 ID の代わりに
name/slugでクエリし、コードを読みやすくします - カスタムフィールドはフィルタリングに
cf_プレフィックスを使用します。(4.7) 選択/複数選択の値は{"value": "prod", "label": "Production"}として読み込まれます。cf["x"]["value"]と比較し、生の値を書き込みます(オブジェクトをそのまま返すと検証に失敗します) - タグを使用すると、オブジェクトタイプをまたいだ分類ができます
- テナントによってリソースを論理的に分離できます
依存関係の完全な順序、階層図、カスタムフィールド、タグ、テナント分離のパターンについては、references/data-modeling.md を参照してください。
インテグレーションツール
pynetbox(Python クライアント)
現在のリリース:7.9.0(2026-10-08。NetBox 4.7 のサポートを明示した最初のリリース。Python 3.12+ が必要)。4.7 では 7.9.0 以降を使用してください。{value, label} 形式の選択カスタムフィールドをフラット化し、更新時には変更されたカスタムフィールドのみを送信するため、複数選択カスタムフィールドを持つオブジェクトの保存に成功します(7.8.0 では失敗する場合があります)。7.9.0 では、作成、save()、update()、delete()(一括操作を含む)で changelog_message= も受け付けます。また、より多くのリストフィールド(object_types、permissions、groups、ルートターゲット、config-context のスコープ)を集合として比較するため、並べ替えによって PATCH が発生することはなくなります。
import pynetbox
nb = pynetbox.api("https://netbox.example.com", token="nbt_abc123.xxxxxxxxxxxxxxxx",
pagination="cursor") # 7.8+: keyset paging on NetBox 4.6+; falls back to offset on older servers
devices = nb.dcim.devices.filter(site="nyc-dc1", status="active") # Auto-paginated
device = nb.dcim.devices.get(name="switch-01")
device.status = "planned"
device.save() # Uses PATCH
pagination="cursor"は逐次処理され(threading=Trueは無視されます)、orderingと併用できません。また、len(record_set)を呼び出すと追加のカウントリクエストが発生します。pynetbox.extensionsのextensions=[BranchingExtension]/[CustomObjectsExtension](7.8+)を使用すると、型付きレコードとプラグインアクションが追加されます。詳しくはBranchingを参照してください。- NetBox 4.7 では、選択フィールドの
record.custom_fields["x"]は{"value", "label"}の辞書です。
Diode(データ取り込み)
一括取り込みには、直接 API を使用する代わりに Diode を使用してください。依存関係は名前で指定します。Diode が自動的に解決するか、作成します。依存関係の順序付けは不要です。
from netboxlabs.diode.sdk import DiodeClient
from netboxlabs.diode.sdk.ingester import Device, Entity
with DiodeClient(target="grpc://diode.example.com:8080/diode",
app_name="discovery", app_version="1.0.0") as client:
device = Device(name="switch-01", device_type="Catalyst 9300",
manufacturer="Cisco", site="NYC-DC1", role="Access Switch")
client.ingest([Entity(device=device)])
Diode の用途:ネットワークの検出、一括移行、関連オブジェクトを多数作成するスクリプト。 REST/GraphQL の用途:データの読み取り、単一オブジェクトの CRUD、複雑なクエリ。
一括取り込み、ネストされたオブジェクト、ドライランモード、認証、サポートされているエンティティタイプについては、references/diode-integration.md を参照してください。
Webhook
Webhook を使用して変更をプッシュするよう NetBox を設定します。X-Hook-Signature ヘッダー(HMAC-SHA512)を必ず検証してください。イベントには created、updated、deleted があり、オブジェクトデータ全体と変更前/変更後のスナップショットが含まれます。
変更追跡
監査証跡を確認するには extras.object_changes をクエリします。タイムスタンプ、アクション、ユーザー、変更前/変更後のデータが含まれます。
ブランチ機能(プラグイン)
netbox-branching プラグインが必要です。NetBox 4.7 では v1.2.x、NetBox 4.4~4.6 では v1.1.x を使用してください。プラグインのセットアップとワークフローについては、netbox-branching を参照してください。
ライフサイクル:作成 → 待機(PROVISIONING→READY)→ 作業 → 同期 → マージ
- コンテキストヘッダー:
X-NetBox-Branch: {schema_id}— 名前や数値 ID ではなく、8 文字のschema_idを使用します - 非同期操作:sync/merge/revert は Job オブジェクトを返します。
status == "completed"になるまでjob["url"]をポーリングします - ドライラン:すべての非同期操作で
{"commit": false}を指定すると、検証を実行できます - pynetbox 7.8+:
pynetbox.api(..., extensions=[BranchingExtension])を使うとbranch.sync()/merge()/revert()が利用できます(Job レコードを返します。競合がexc.errorに含まれる場合、確認されるまでは 409 になります)。また、with nb.activate_branch(branch):を使うと、ヘッダーが自動的に設定されます
ブランチの完全なライフサイクル、コンテキストヘッダーの使用方法、非同期ジョブのポーリング、セッションラッパーのパターンについては、references/branching-patterns.md を参照してください。
バージョンに関する注意事項
NetBox 4.7.3(2026-10-13)
- デバイス/VM の一覧・詳細取得で
?omit=config_context、?fields=(config_contextを含めない場合)、または?brief=Trueを指定すると、config-context の DB アノテーションとキャッシュ済みカラムも再び省略されます(#23288。?exclude=は引き続き何もしません)。また、?background=trueを指定した一括書き込みでは、リクエストヘッダーとクエリ文字列がワーカーに引き継がれるため、X-NetBox-Branchが尊重されます(#23247 — 4.7.0~4.7.2 では引き継がれず、書き込みは main に反映されていました)。4.7.3 以降を実行してください。4.7.0/4.7.1 ではトークンの平文がジョブ結果に漏れていました。4.7.3 では、ブランチに対応したバックグラウンド書き込みと config-context 省略の最適化が追加されています。
NetBox 4.7(2026-09-02。4.7.3 以降を実行)
- 4.7.x 全体で
?exclude=config_contextは通知なく無視されます。config_contextはデバイス/VM 上で事前にレンダリングされ、キャッシュされます。4.7.0~4.7.2 では常に読み込まれます(?fields=、?omit=config_context、?brief=Trueはペイロードのみを削減します)。4.7.3 以降では、これらのパラメーターによって DB 処理も省略されます。 - 選択式/複数選択式のカスタムフィールドは
{value, label}として読み取られます(REST + GraphQL)。書き込み時は生の値を指定します。 - 一括書き込み:
?background=true→ 202 + ジョブ(ポーリングしてください。If-Matchがある場合は 400、ワーカーがない場合は 503)。一括作成/更新に失敗すると、オブジェクトごとのerrorsが返されます。一括操作は引き続き全件成功または全件失敗です。ブランチ内では、4.7.0~4.7.2 のX-NetBox-Branchは引き継がれません(書き込みは main に反映されます)。4.7.3 以降では引き継がれます。 - トークン:作成時の
tokenは読み取り専用です。/api/users/tokens/では?background=trueが拒否されます(4.7.2。これ以前の 4.7.x では平文がジョブ結果に漏れていました)。REST 経由でスクリプトを実行するには、書き込み可能なトークンが必要です。 - サービス:
protocol/portsはport_mappingsに置き換えられました(["tcp/53", "udp/53"])。従来のペアは非推奨で、5.0 で削除されます。protocol__ic形式やport__emptyのルックアップは廃止されました。references/data-modeling.md を参照してください。 - Interface/VMInterface の
mac_addressは書き込み可能です(プライマリ MAC を作成または更新します)。MACAddress.is_primaryは読み取り専用です。 - 新しいエンドポイント:
dcim/cooling-sources|cooling-feeds|cooling-intakes|cooling-outflows|cooling-intake-templates|cooling-outflow-templates/、dcim/module-bay-types/。新しいフィールド:end_of_life(DeviceType/ModuleType)、channels/channel_id(Interface)、Job.execution_time、Webhook.timeout、CustomField.status/nulls_first。 - アップグレードの前提条件(PostgreSQL 15+、
ltree、Redis 6+)と、時間のかかる MPTT→ltree 移行については、netbox-administration で説明しています。
NetBox 4.6
- REST カーソルページネーション(
?start=)、ETag/If-Match、add_tags/remove_tags。v1 トークンは非推奨(5.0 で削除)。トークンの平文は一度だけ返されます(4.6.1 以降)。GRAPHQL_MAX_QUERY_DEPTHがサーバー側で適用されます(4.6.1 以降)。VM でclusterが任意になりました。