
Kuroco Api Content
- 35 installs
- 1 repo stars
- Updated July 27, 2026
- diverta/kuroco-skills
kuroco-api-content is an agent skill that documents Kuroco RCMS file upload, image URLs, and news bulk upsert API usage.
About
kuroco-api-content is an agent skill for solo builders maintaining sites on Kuroco (RCMS): it documents file upload to the files API, binding file_id into content insert JSON, public image URLs on the Kuroco image host with resize query parameters, and CSV-style bulk upsert against the news bulk endpoint. The readme is JavaScript fetch-oriented with credentials included, which matches admin-authenticated or session-backed workflows common in headless CMS migrations and small agency stacks. Use it during build when you are scripting imports, syncing editorial content from spreadsheets, or wiring file fields on custom columns—not for generic React UI polish. Agents can translate the patterns into your framework’s HTTP client. You still need a Kuroco site key, API paths, and field keys (subject, contents, ymd, topics_flg) matching your schema. Prism catalogs this as integration knowledge, not a hosted connector service.
- POST /rcms-api/1/files/upload with FormData and cookie credentials
- Attach uploaded file_id to content insert payloads (e.g. news ext_col fields)
- Documented Kuroco image CDN URL pattern on g.kuroco-img.app with width/height/fit params
- bulk_upsert via POST /rcms-api/1/news/bulk with list of topics rows
- Supports create and update rows when topics_id is supplied in bulk items
Kuroco Api Content by the numbers
- 35 all-time installs (skills.sh)
- Ranked #3,328 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Security screen: HIGH risk (skills.sh audit)
- Data as of Jul 29, 2026 (Skillselion catalog sync)
npx skills add https://github.com/diverta/kuroco-skills --skill kuroco-api-contentAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 35 |
|---|---|
| repo stars | ★ 1 |
| Security audit | 2 / 3 scanners passed |
| Last updated | July 27, 2026 |
| Repository | diverta/kuroco-skills ↗ |
What it does
Let your agent generate Kuroco RCMS API calls for file upload, content insert with file_id, image CDN URLs, and news bulk_upsert CSV flows.
Who is it for?
Developers and maintainers automating Kuroco content migration or recurring CSV syncs with session/cookie auth.
Skip if: Projects not on Kuroco RCMS or teams that only need front-end theming without API writes.
When should I use this skill?
When implementing Kuroco file upload, attaching files to content fields, building image CDN URLs, or running news bulk upsert from code.
What you get
You have copy-ready fetch patterns for upload, content insert with file linkage, CDN image URLs, and bulk news list payloads.
- Upload helper returning file_id from /files/upload
- Bulk upsert payload mapping spreadsheet rows to news list entries
Files
Kuroco API連携 & コンテンツ管理
Kuroco HeadlessCMSのAPI設計・実装およびコンテンツ管理に関するベストプラクティス。
ドキュメント参照: /kuroco-docs スキルを使用してKuroco公式ドキュメントを検索・参照できます。
目次
Part 1: API連携パターン
Part 2: コンテンツ管理パターン
- コンテンツ構造
- 拡張項目(カスタムフィールド)
- Topics API オペレーション
- コンテンツCRUD操作
- フィルタークエリ → 詳細は references/filter-query.md
- ファイル・CSV操作 → 詳細は references/file-operations.md
- 管理API(admin_api)によるコンテンツ操作
---
Part 1: API連携パターン
エンドポイント設計
基本構造
KurocoのAPIパスは以下の形式:
https://{サイトキー}.g.kuroco.app/rcms-api/{api_id}/{endpoint_path}例:
https://example.g.kuroco.app/rcms-api/1/news
https://example.g.kuroco.app/rcms-api/1/member/loginエンドポイント設定の主要項目
| 項目 | 説明 | 例 |
|---|---|---|
| パス | エンドポイントのURL | news, member/list |
| モデル | 操作対象 | Topics, Member, InquiryForm |
| オペレーション | 操作種別 | list, details, insert, update, delete |
| キャッシュ | レスポンスキャッシュ期間 | 86400(1日) |
| 流量制限 | リクエスト数制限 | 100回/分 |
| 認証必須 | ログイン必須かどうか | true/false |
主要カテゴリとモデル
認証(Authentication)
| オペレーション | 説明 | メソッド |
|---|---|---|
login_challenge | ログイン | POST |
token | アクセストークン取得 | POST |
logout | ログアウト | POST |
profile | ログインユーザー情報取得 | GET |
reminder | パスワードリマインダー | POST |
コンテンツ(Topics)
| オペレーション | 説明 | メソッド |
|---|---|---|
list | 一覧取得 | GET |
details | 詳細取得 | GET |
insert | 新規追加 | POST |
update | 更新 | POST |
delete | 削除 | POST |
bulk_upsert | 一括更新 | POST |
メンバー(Member)
| オペレーション | 説明 | メソッド |
|---|---|---|
list | メンバー一覧 | GET |
details | メンバー詳細 | GET |
insert | メンバー登録 | POST |
update | メンバー更新 | POST |
フォーム(InquiryMessage/InquiryForm)
| オペレーション | 説明 | メソッド |
|---|---|---|
send | フォーム送信 | POST |
list | 回答一覧 | GET |
details | 回答詳細 | GET |
セキュリティ設定
詳細リファレンス: セキュリティ設定の詳細は references/security-settings.md を参照してください。
>
公式ドキュメント: 詳細な公式情報は ../kuroco-docs/docs/management/api-security.md 等を参照してください。認証方式
管理画面: [API] → [セキュリティ] で4種類から選択。
| 認証方式 | 用途 | ヘッダー |
|---|---|---|
| なし | 開発・テスト用(本番非推奨) | 不要 |
| 静的アクセストークン | サーバー間通信、公開API | X-RCMS-API-ACCESS-TOKEN: {固定トークン} |
| 動的アクセストークン | ログイン必須サイト(JWT) | X-RCMS-API-ACCESS-TOKEN: {動的トークン} |
| Cookie | ログイン必須Webサイト | credentials: 'include'(フロントエンド側) |
1. Cookie認証(Webアプリ推奨)
セッションベースの認証。credentials: 'include' が必須。
// ログイン
const response = await fetch('https://example.g.kuroco.app/rcms-api/1/login', {
method: 'POST',
credentials: 'include', // 必須
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: 'user@example.com',
password: 'password123'
})
})
// レスポンス例
// {
// "grant_token": "xxxxx",
// "status": 0,
// "member_id": 123
// }注意点:
- サードパーティCookie問題(Safari等でブロックされる)
- APIドメインとフロントエンドを同一ドメイン(サブドメイン違い)に設定が必要(ファーストパーティCookie化)
- 例:
api.example.comとwww.example.com - Cookie認証APIが複数ある場合、各API間で認証状態が共有される
2. トークン認証(モバイルアプリ推奨)
JWTベースの認証。ヘッダーにトークンを付与。
// トークン取得
const tokenResponse = await fetch('https://example.g.kuroco.app/rcms-api/1/token', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: 'user@example.com',
password: 'password123'
})
})
const { access_token, refresh_token } = await tokenResponse.json()
// レスポンス例
// {
// "access_token": {
// "value": "eyJhbGciOiJS...",
// "expiresAt": "2024-01-01T12:00:00+09:00"
// },
// "refresh_token": {
// "value": "xxxxxx",
// "expiresAt": "2024-01-08T12:00:00+09:00"
// }
// }
// API呼び出し時
const response = await fetch('https://example.g.kuroco.app/rcms-api/1/news', {
headers: {
'X-RCMS-API-ACCESS-TOKEN': access_token.value
}
})前提条件: ユーザー1人以上、login_challenge + token エンドポイント必須。トークン認証APIが複数ある場合、各API間で認証状態は共有されない。
3. StaticToken認証(サーバー間通信)
固定トークンによるAPIアクセス制限。
const response = await fetch('https://example.g.kuroco.app/rcms-api/1/internal-api', {
headers: {
'X-RCMS-API-ACCESS-TOKEN': 'your-static-token-here'
}
})設定場所: 管理画面 → API → セキュリティ → StaticToken
注意: 静的トークンはフロントエンドに組み込まれるとユーザーに見える。流出時のトークン更新を想定した運用が必要。
IPアドレス制限
管理画面: [API] → [セキュリティ] → [IPアドレス制限]
指定されたIPアドレスからのアクセスのみ許可します。
| 指定形式 | 例 | 説明 |
|---|---|---|
| 個別IP | 192.0.2.1 | 単一IPアドレス |
| CIDR | 192.0.2.0/24 | サブネット単位 |
| 範囲指定 | 192.0.2.1-192.0.2.2 | ハイフンによるIP範囲 |
IPアドレスグループ: 定数機能で IPSETS_* を定義し、[[IPSETS_*]] で参照可能(../kuroco-docs/docs/faq/is-it-possible-to-set-multiple-ip-addresses-at-once.mdx 参照)。
CORS設定
管理画面: [API] → [セキュリティ] → [CORS]
| 項目 | 対応ヘッダー | 説明 |
|---|---|---|
| CORS_ALLOW_ORIGINS | Access-Control-Allow-Origin | 許可オリジン(*ワイルドカード``は非推奨**) |
| CORS_ALLOW_METHODS | Access-Control-Allow-Methods | 許可HTTPメソッド |
| CORS_ALLOW_HEADERS | Access-Control-Allow-Headers | 許可リクエストヘッダー |
| CORS_MAX_AGE | Access-Control-Max-Age | プリフライトキャッシュ秒数 |
| CORS_ALLOW_CREDENTIALS | Access-Control-Allow-Credentials | Cookie送信の許可 |
CSRF対策: CORS + Content-Type: application/json でモダンブラウザでのCSRF攻撃を防御。ワイルドカードを使うと防御効果がなくなるため、必ず特定ドメインを指定すること。
変更反映の遅延: CORS設定変更後は CORS_MAX_AGE 分だけブラウザにキャッシュされる。即時反映にはブラウザキャッシュクリアまたは CORS_MAX_AGE を 0 に設定。
APIリクエスト制限
| 制限タイプ | 説明 |
|---|---|
| None | 制限なし |
| GroupAuth | ログインユーザーのグループ権限をチェックし、合致した場合のみ許可 |
| MemberCustomSearchAuth | ログインユーザーがカスタムメンバーフィルターの条件に合致する場合のみ許可 |
閲覧制限の優先順序
コンテンツ返却時の制限は以下の順序で評価されます(上位優先):
1. API → IPアドレス制限(API全体) 2. エンドポイント → APIリクエスト制限(エンドポイント単位) 3. コンテンツ定義 → APIリクエスト制限 4. コンテンツカテゴリ → APIリクエスト制限 5. 個別コンテンツ → APIリクエスト制限
後処理によるレスポンス制限
管理画面: [API] → エンドポイント → [後処理]
APIレスポンスから不要なフィールドを除外し、公開情報を制御:
| 処理タイプ | 説明 |
|---|---|
| 出力許可リスト | 指定フィールドのみ返す(ホワイトリスト)。例: list.subject, pageInfo |
| 出力変換リスト | フィールドの削除・名称変更・変換関数の適用 |
| カスタム処理 | Smartyテンプレートでの独自ロジック |
パフォーマンスTip: 出力許可リストは他の処理の前に配置するとSQLレベルで効果あり。
プラットフォームセキュリティ
Kurocoプラットフォームが提供するインフラレベルのセキュリティ:
- 通信: HTTPS完全暗号化、TLS証明書自動管理
- 防御: WAF、CDN、DDoS対策(オプションでFastly DDoS Protection)
- 認証連携: SAML/OAuth外部ログイン、クライアント証明書(オプション)
- 監査: アクセスログ、アプリケーションログ
- 認定: ISMS (ISO 27001)、ISMSクラウド (ISO 27017)、プライバシーマーク
- 診断: 毎日のコンテナ脆弱性スキャン、VADDY連携自動診断
管理API(admin_api)による設定変更
APIのセキュリティ設定は管理画面だけでなく、管理API経由でも操作可能です。/kuroco-admin-api スキルを使用してCLI経由で管理APIを実行できます。
キャッシュ戦略
推奨設定
| ユースケース | キャッシュ期間 | 設定値 |
|---|---|---|
| 静的コンテンツ(ニュース等) | 1日 | 86400 |
| 更新頻度低いコンテンツ | 1週間 | 604800 |
| リアルタイム性が必要 | キャッシュなし | 0 |
| 認証が必要なAPI | キャッシュなし | 0 |
重要: コンテンツ・メンバー等のデータ更新時、キャッシュは自動クリアされます。
キャッシュヘッダー
レスポンスヘッダーで確認可能:
Cache-Control: max-age=86400流量制限
レスポンスヘッダー
x-rcms-ratelimit-limit: 100 # 制限数
x-rcms-ratelimit-remaining: 95 # 残りリクエスト数
x-rcms-ratelimit-reset: 60 # リセットまでの秒数429エラー時の対応
const response = await fetch(url)
if (response.status === 429) {
const resetTime = response.headers.get('x-rcms-ratelimit-reset')
throw new Error(`流量制限超過。${resetTime}秒後に再試行してください`)
}API呼び出しパターン
一覧取得(ページネーション付き)
async function fetchNewsList(page = 1, perPage = 10) {
const params = new URLSearchParams({
pageID: page,
cnt: perPage
})
const response = await fetch(
`https://example.g.kuroco.app/rcms-api/1/news?${params}`,
{ credentials: 'include' }
)
const data = await response.json()
// レスポンス構造
// {
// "list": [...],
// "pageInfo": {
// "totalCnt": 100,
// "perPage": 10,
// "totalPageCnt": 10,
// "pageNo": 1
// }
// }
return data
}フィルター検索
// filter パラメータで検索
const params = new URLSearchParams({
filter: 'subject contains "重要"',
order_by: 'ymd desc'
})
const response = await fetch(
`https://example.g.kuroco.app/rcms-api/1/news?${params}`,
{ credentials: 'include' }
)詳細取得
async function fetchNewsDetail(topicsId) {
const response = await fetch(
`https://example.g.kuroco.app/rcms-api/1/newsdetail/${topicsId}`,
{ credentials: 'include' }
)
const data = await response.json()
// レスポンス構造
// {
// "details": {
// "topics_id": 1,
// "subject": "タイトル",
// "contents": "<p>本文</p>",
// ...
// }
// }
return data.details
}コンテンツ作成
async function createNews(newsData) {
const response = await fetch(
'https://example.g.kuroco.app/rcms-api/1/news/insert',
{
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
subject: newsData.title,
contents: newsData.body,
ymd: newsData.date,
topics_flg: 1 // 1: 公開, 0: 非公開
})
}
)
return response.json()
}エラーハンドリング
主要エラーコード
| コード | 説明 | 対応 |
|---|---|---|
| 400 | リクエストエラー | リクエストパラメータを確認 |
| 401 | 認証エラー | ログイン状態・トークンを確認 |
| 403 | 権限エラー | APIの権限設定を確認 |
| 404 | リソース未存在 | パス・IDを確認 |
| 429 | 流量制限超過 | リトライまで待機 |
| 500 | サーバーエラー | Kurocoサポートに連絡 |
エラーレスポンス例
{
"errors": [
{
"code": "authentication_error",
"message": "ログインが必要です"
}
]
}エラーハンドリング実装
async function apiRequest(url, options = {}) {
const response = await fetch(url, {
credentials: 'include',
...options
})
if (!response.ok) {
const errorData = await response.json()
switch (response.status) {
case 401:
throw new Error('認証が必要です')
case 403:
throw new Error('アクセス権限がありません')
case 429:
throw new Error('リクエスト制限を超えました')
default:
throw new Error(errorData.errors?.[0]?.message || 'APIエラー')
}
}
return response.json()
}---
Part 2: コンテンツ管理パターン
コンテンツ構造
階層構造
コンテンツ定義(TopicsGroup)
├── カテゴリ(TopicsCategory)
│ └── コンテンツ(Topics)
└── 拡張項目(ext_col_01〜ext_col_XX)コンテンツ定義の設定
管理画面: [コンテンツ定義] → [新規作成]
| 項目 | 説明 |
|---|---|
| グループ名 | コンテンツ定義の名前 |
| 識別子 | ユニークなID(英数字) |
| 本文の入力方法 | WYSIWYG、マークダウン、HTML |
| 閲覧制限 | 全員/グループ制限/カスタム検索 |
| 編集制限 | 全員/グループ制限/カスタム検索 |
| 拡張項目 | カスタムフィールド(最大99個) |
拡張項目(カスタムフィールド)
| タイプ | 説明 | APIレスポンス例 |
|---|---|---|
| テキスト | 1行テキスト | "ext_col_01": "値" |
| テキストエリア | 複数行テキスト | "ext_col_02": "複数行\nテキスト" |
| WYSIWYG | リッチテキスト | "ext_col_03": "<p>HTML</p>" |
| 数値 | 整数・小数 | "ext_col_04": 100 |
| 日付 | 日付選択 | "ext_col_05": "2024-01-01" |
| 選択(単一) | ラジオボタン | "ext_col_06": "選択肢1" |
| 選択(複数) | チェックボックス | "ext_col_07": ["選択肢1", "選択肢2"] |
| ファイル/画像 | アップロード | "ext_col_08": { "id": "xxx", "url": "https://...", "desc": "" } |
| リンク | URLリンク | "ext_col_10": { "url": "https://...", "title": "リンク名" } |
| 関連コンテンツ | 他コンテンツ参照 | "ext_col_11": { "topics_id": 123, "subject": "タイトル" } |
Topics API オペレーション
| オペレーション | 説明 | メソッド | パス例 |
|---|---|---|---|
| list | 一覧取得 | GET | /news |
| details | 詳細取得 | GET | /newsdetail/{topics_id} |
| insert | 新規追加 | POST | /news/insert |
| update | 更新 | POST | /news/update/{topics_id} |
| delete | 削除 | POST | /news/delete/{topics_id} |
| bulk_upsert | 一括更新 | POST | /news/bulk |
コンテンツCRUD操作
一覧取得レスポンス
{
"list": [
{
"topics_id": 1,
"subject": "タイトル",
"contents": "本文(HTML)",
"ymd": "2024-01-01",
"topics_flg": 1,
"category_id": 1,
"ext_col_01": "拡張項目値",
"tag": ["タグ1", "タグ2"]
}
],
"pageInfo": {
"totalCnt": 100,
"perPage": 10,
"totalPageCnt": 10,
"pageNo": 1
}
}コンテンツ作成
const response = await fetch('/rcms-api/1/news/insert', {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
subject: 'タイトル',
contents: '<p>本文</p>',
ymd: '2024-01-01',
topics_flg: 1, // 1: 公開, 0: 非公開
category_id: 1,
open_ymd: '2024-12-01', // 予約公開開始日
close_ymd: '2024-12-31', // 公開終了日
tag: ['タグ1', 'タグ2'],
ext_col_01: 'カスタム値'
})
})コンテンツ更新
const response = await fetch(`/rcms-api/1/news/update/${topicsId}`, {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
subject: '更新タイトル',
contents: '更新本文'
// 更新したいフィールドのみ送信可能
})
})コンテンツ削除
await fetch(`/rcms-api/1/news/delete/${topicsId}`, {
method: 'POST',
credentials: 'include'
})フィルタークエリ
基本構文: filter={field} {operator} {value}
| 演算子 | 例 |
|---|---|
=, != | filter=category_id = 1 |
>, >=, <, <= | filter=ymd >= '2024-01-01' |
contains | filter=subject contains 'キーワード' |
in, not_in | filter=category_id in [1, 2, 3] |
複合条件: filter=(category_id = 1 or category_id = 2) and topics_flg = 1
ソート: order_by=ymd desc
詳細な使い方: references/filter-query.md を参照
ファイル・CSV操作
ファイルアップロード
// 1. ファイルアップロード
const formData = new FormData()
formData.append('file', file)
const result = await fetch('/rcms-api/1/files/upload', {
method: 'POST',
credentials: 'include',
body: formData
})
const { file_id } = await result.json()
// 2. コンテンツに紐付け
await fetch('/rcms-api/1/news/insert', {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
subject: 'タイトル',
ext_col_02: { file_id, desc: '説明' }
})
})詳細(一括更新、カテゴリ、タグ、閲覧制限): references/file-operations.md を参照
管理API(admin_api)によるコンテンツ操作
/kuroco-admin-api スキルを使うと、管理画面と同等のコンテンツ操作をCLI経由で実行できます。フロントエンドAPI(rcms-api)との違いに注意してください。
フロントエンドAPI vs 管理API
| 項目 | フロントエンドAPI(rcms-api) | 管理API(admin_api) |
|---|---|---|
| 対象 | エンドユーザー | 管理者・運用者 |
| 認証 | StaticToken / DynamicToken / Cookie | 管理画面セッションCookie |
| エンドポイント | /rcms-api/{api_id}/{path} | /direct/rcms_api/admin_api/ |
| 利用場面 | フロントエンド実装 | データ一括操作、構造確認、設定変更 |
コンテンツ定義一覧の取得
# admin_api: コンテンツ定義(TopicsGroup)一覧(columnsで必要カラムのみ取得)
kuroco-admin exec topics/topics_group_list --columns topics_group_id,group_nm --jsonコンテンツ一覧の取得
# admin_api: 特定コンテンツ定義のコンテンツ一覧(columnsで必要カラムのみ取得)
kuroco-admin exec topics/topics_list --param "topics_group_id[]=1" --param cnt=10 --columns topics_id,subject,ymd --jsonコンテンツの作成
# admin_api: コンテンツ作成(※実行前にユーザー確認必須)
kuroco-admin exec topics/topics_edit --MODE INSERT --data '{"subject":"タイトル","contents":"本文","topics_group_id":1,"topics_flg":1}' --json活用シーン
- サイト構造の把握: コンテンツ定義一覧・拡張項目の確認
- データの一括確認・修正: 管理画面GUIを経由せず効率的にデータ操作
- スキーマ確認:
kuroco-admin help topics/topics_edit --jsonでフィールド定義を取得
注意: insert/update/deleteは必ずユーザーに確認してから実行すること。詳細は /kuroco-admin-api スキル参照。ベストプラクティス
- キャッシュ活用: エンドポイント設定で
キャッシュ: 86400(1日)を設定。更新時は自動クリア - ページネーション:
pageIDとcntパラメータで分割取得
---
関連スキル
/kuroco-frontend-integration- Nuxt.js/Next.jsでのAPI呼び出しパターン、AI自動デプロイ/kuroco-server-processing- Smartyプラグイン・構文リファレンス、Webhook・バッチ処理/kuroco-admin-api- 管理API(admin_api)の操作
関連ドキュメント
スキル内リファレンス
- references/security-settings.md - セキュリティ設定の詳細リファレンス
- references/filter-query.md - フィルタークエリ詳細
- references/file-operations.md - ファイル・CSV操作詳細
Kuroco公式ドキュメント
../kuroco-docs/docs/management/api-security.md- APIセキュリティ設定(認証方式、IP制限)../kuroco-docs/docs/management/api-list.md- API一覧・CORS設定../kuroco-docs/docs/management/api-postprocessing.md- API後処理の設定../kuroco-docs/docs/reference/endpoint-settings.md- エンドポイント設定項目一覧../kuroco-docs/docs/reference/post-processing.md- 後処理の詳細リファレンス../kuroco-docs/docs/tutorials/configure-endpoint.md- エンドポイント設定方法../kuroco-docs/docs/tutorials/login.md- ログイン実装../kuroco-docs/docs/tutorials/restricting-api-access-with-statictoken.md- StaticToken認証../kuroco-docs/docs/reference/api-cache.md- APIキャッシュ../kuroco-docs/docs/reference/filter-query.md- フィルタークエリ../kuroco-docs/docs/about/security.md- プラットフォームセキュリティ概要../kuroco-docs/docs/faq/in-what-order-are-viewing-restrictions-applied.mdx- 閲覧制限の優先順序../kuroco-docs/docs/faq/cors-and-content-type-prevent-csrf-attacks.mdx- CSRF対策../kuroco-docs/docs/faq/the-api-returns-403-forbidden-even-though-no-restrictions-are-applied.mdx- 403エラーの解決../kuroco-docs/docs/tutorials/adding-a-topics.md- コンテンツ定義作成../kuroco-docs/docs/tutorials/bulk-upload-in-csv.md- CSVアップロード../kuroco-docs/docs/management/content-structure-topics.md- コンテンツ構造
ファイル操作・CSVインポート
ファイルアップロード
1. ファイルをアップロード
async function uploadFile(file) {
const formData = new FormData()
formData.append('file', file)
const response = await fetch('/rcms-api/1/files/upload', {
method: 'POST',
credentials: 'include',
body: formData
})
const result = await response.json()
return result.file_id
}2. コンテンツに紐付け
// アップロード後、file_idをコンテンツに紐付け
const fileId = await uploadFile(file)
await fetch('/rcms-api/1/news/insert', {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
subject: 'タイトル',
ext_col_02: {
file_id: fileId,
desc: 'ファイルの説明'
}
})
})画像URL形式
https://{サイトキー}.g.kuroco-img.app/files/{ディレクトリ}/{ファイル名}画像変換パラメータ:
?width=300&height=200&fit=coverCSVインポート/エクスポート
一括アップロード(bulk_upsert)
async function bulkUpsert(items) {
const response = await fetch('/rcms-api/1/news/bulk', {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
list: items.map(item => ({
topics_id: item.id, // 既存更新の場合
subject: item.title,
contents: item.body,
ymd: item.date,
topics_flg: 1
}))
})
})
return response.json()
}
// 使用例
await bulkUpsert([
{ title: 'タイトル1', body: '本文1', date: '2024-01-01' },
{ id: 123, title: '更新タイトル', body: '更新本文' } // 既存更新
])カテゴリ管理
カテゴリ一覧取得
パス: categories
カテゴリー: コンテンツ
モデル: TopicsCategory
オペレーション: list
topics_group_id: {グループID}レスポンス構造
{
"list": [
{
"topics_category_id": 1,
"category_nm": "カテゴリ名",
"parent_id": 0,
"category_weight": 1,
"child": [
{
"topics_category_id": 2,
"category_nm": "子カテゴリ",
"parent_id": 1
}
]
}
]
}タグ管理
タグの設定
// コンテンツ作成/更新時
{
"subject": "タイトル",
"tag": ["タグ1", "タグ2", "タグ3"]
}タグでフィルター
const params = new URLSearchParams({
filter: "tag contains 'タグ1'"
})閲覧/編集制限
閲覧制限の種類
| 種類 | 説明 |
|---|---|
| 選択なし | 全員閲覧可能 |
| グループ制限 | 特定グループのメンバーのみ |
| メンバーカスタム検索 | 条件に合致するメンバーのみ |
制限適用の優先順位
1. コンテンツ定義の設定 2. カテゴリの設定 3. 個別コンテンツの設定
フィルタークエリ詳細
基本構文
filter={field} {operator} {value}演算子一覧
| 演算子 | 説明 | 例 |
|---|---|---|
= | 等しい | filter=category_id = 1 |
!= | 等しくない | filter=topics_flg != 0 |
> | より大きい | filter=topics_id > 100 |
>= | 以上 | filter=ymd >= '2024-01-01' |
< | より小さい | filter=topics_id < 100 |
<= | 以下 | filter=ymd <= '2024-12-31' |
contains | 部分一致 | filter=subject contains 'キーワード' |
not_contains | 部分一致しない | filter=subject not_contains '除外' |
in | いずれかに一致 | filter=category_id in [1, 2, 3] |
not_in | いずれにも一致しない | filter=category_id not_in [1, 2] |
複合条件
// AND条件
const params = new URLSearchParams({
filter: "category_id = 1 and ymd >= '2024-01-01'"
})
// OR条件
const params = new URLSearchParams({
filter: "category_id = 1 or category_id = 2"
})
// 複合条件
const params = new URLSearchParams({
filter: "(category_id = 1 or category_id = 2) and topics_flg = 1"
})ソート
// 降順(新しい順)
const params = new URLSearchParams({
order_by: 'ymd desc'
})
// 昇順
const params = new URLSearchParams({
order_by: 'topics_id asc'
})
// 複数条件
const params = new URLSearchParams({
order_by: 'category_id asc, ymd desc'
})ページネーション
const params = new URLSearchParams({
pageID: '2', // ページ番号(1始まり)
cnt: '20' // 1ページあたりの件数
})
const response = await fetch(`/rcms-api/1/news?${params}`)全件取得のページネーション実装
async function fetchAllNews() {
let allItems = []
let page = 1
let hasMore = true
while (hasMore) {
const response = await fetch(`/rcms-api/1/news?pageID=${page}&cnt=100`)
const data = await response.json()
allItems = [...allItems, ...data.list]
hasMore = page < data.pageInfo.totalPageCnt
page++
}
return allItems
}検索機能の実装例
async function searchNews(keyword, categoryId) {
const filters = []
if (keyword) {
filters.push(`subject contains '${keyword}'`)
}
if (categoryId) {
filters.push(`category_id = ${categoryId}`)
}
const params = new URLSearchParams({
filter: filters.join(' and '),
order_by: 'ymd desc'
})
const response = await fetch(`/rcms-api/1/news?${params}`)
return response.json()
}Kuroco APIセキュリティ設定 詳細リファレンス
このドキュメントは api-integration スキルのセキュリティセクションの補足資料です。 Kuroco公式ドキュメントから抽出・整理した情報に基づいています。
---
1. 認証方式の詳細
管理画面: [API] → [セキュリティ] で設定します。
選択肢一覧
| 認証方式 | 用途 | 特徴 |
|---|---|---|
| なし | 開発・テスト用 | トークンなしでアクセス可能。本番環境では非推奨 |
| 静的アクセストークン(StaticToken) | サーバー間通信、公開API | 固定トークン。流出リスクがあるため更新運用を想定すること |
| 動的アクセストークン(DynamicToken) | ログイン必須サイト | JWT。ログイン毎にワンタイムトークンを動的生成 |
| Cookie | ログイン必須Webサイト | セッションベース。サードパーティCookie規制への対応が必要 |
動的アクセストークンの前提条件
- ユーザーが1人以上登録されていること
- 必須エンドポイントの作成:
Login(v1)::login_challenge(ログイン)Login(v1)::token(トークン取得)- フロントエンドでのトークンマネジメント実装
- 注意: トークン認証APIが複数ある場合、各API間で認証状態は共有されない
Cookie認証の前提条件
- ユーザーが1人以上登録されていること
- 必須エンドポイント:
Login(v1)::login_challenge - フロントとKurocoのドメインを合わせる必要がある(ファーストパーティCookie化)
- 注意: Cookie認証APIが複数ある場合、各API間で認証状態が共有される
リクエストヘッダーの指定
# 静的トークン / 動的トークン共通
X-RCMS-API-ACCESS-TOKEN: {トークン値}---
2. IPアドレス制限
管理画面: [API] → [セキュリティ] → [IPアドレス制限]
指定されたIPアドレスからのアクセスのみ許可する機能です。
指定形式
| 形式 | 例 | 説明 |
|---|---|---|
| 個別IP | 192.0.2.1 | 単一IPアドレス |
| CIDR | 192.0.2.0/24 | サブネット単位(この例では192.0.2.0〜192.0.2.255) |
| 範囲指定 | 192.0.2.1-192.0.2.2 | ハイフンによるIP範囲指定 |
IPアドレスグループ(IPSETS)
複数のIPアドレスをまとめて管理するには、定数機能を利用します。
1. 管理画面: [環境設定] → [定数] で IPSETS_* の名前で定数を作成 2. 改行区切りでIPアドレスを入力(#コメント 形式でメモ可) 3. IPアドレス制限欄に [[IPSETS_*]] と入力して参照
# 定数設定例(名前: IPSETS_OFFICE)
192.0.2.1 #東京オフィス
192.0.2.10 #大阪オフィス
10.0.0.0/8 #VPN参考ドキュメント
../../kuroco-docs/docs/management/api-security.md- IPアドレス制限の設定画面../../kuroco-docs/docs/faq/is-it-possible-to-set-multiple-ip-addresses-at-once.mdx- IPSETS機能
---
3. APIリクエスト制限(エンドポイント単位)
管理画面: [API] → エンドポイント設定 → [APIリクエスト制限]
| 制限タイプ | 説明 |
|---|---|
| None | 制限なし。認証不要のエンドポイント向け |
| GroupAuth | ログインユーザーのグループ権限をチェックし、合致した場合のみリクエストを許可 |
| MemberCustomSearchAuth | ログインユーザーがカスタムメンバーフィルターの検索条件に合致する場合のみリクエストを許可 |
GroupAuth
- メンバーが所属するグループに基づいてアクセス制御
- グループ設定: 管理画面 → [メンバー管理] → [グループ]
MemberCustomSearchAuth
- カスタムメンバーフィルターで定義した複合条件でアクセス制御
- 条件例: 登録日、グループ、都道府県、カスタム項目など
- フィルター設定: 管理画面 → [メンバー管理] → [カスタムメンバーフィルター]
- フィルターの「権限設定への利用」を有効にする必要がある
参考ドキュメント
../../kuroco-docs/docs/reference/endpoint-settings.md- APIリクエスト制限の項目説明../../kuroco-docs/docs/tutorials/using-custom-member-filters.md- カスタムメンバーフィルターの使い方
---
4. 閲覧制限の優先順序
コンテンツを返すAPIでは、以下の順序で閲覧制限が評価されます(上位が優先):
1. API → セキュリティ → IPアドレス制限 (API全体) 2. API → エンドポイント設定 → APIリクエスト制限 (エンドポイント単位) 3. コンテンツ定義 → APIリクエスト制限 (コンテンツ定義単位) 4. コンテンツカテゴリ → APIリクエスト制限 (カテゴリ単位) 5. 個別コンテンツ → APIリクエスト制限 (コンテンツ単位)
上位レベルで拒否されると、下位レベルの設定に関わらずアクセスは拒否されます。
参考ドキュメント
../../kuroco-docs/docs/faq/in-what-order-are-viewing-restrictions-applied.mdx
---
5. CORS設定
管理画面: [API] → [セキュリティ] → [CORS]
| 項目 | 対応ヘッダー | 説明 | 設定例 |
|---|---|---|---|
| CORS_ALLOW_ORIGINS | Access-Control-Allow-Origin | 許可するオリジン(複数設定可) | http://localhost:3000, https://your-site.com |
| CORS_ALLOW_METHODS | Access-Control-Allow-Methods | 許可するHTTPメソッド | GET, POST, OPTIONS |
| CORS_ALLOW_HEADERS | Access-Control-Allow-Headers | 許可するリクエストヘッダー | * |
| CORS_MAX_AGE | Access-Control-Max-Age | プリフライトのキャッシュ秒数 | 600 |
| CORS_ALLOW_CREDENTIALS | Access-Control-Allow-Credentials | Cookie送信の許可 | true |
重要な注意点
- *ワイルドカード(``)をORIGINSに使用しないこと**: CSRF攻撃への防御効果がなくなる
- CORS設定はContent-Security-Policyの
frame-ancestorsにも反映される - CORS変更後の反映遅延:
CORS_MAX_AGEで指定された秒数だけブラウザにキャッシュされる。即時反映するにはブラウザキャッシュクリアまたはCORS_MAX_AGEを0に設定 - Cookie認証では
CORS_ALLOW_CREDENTIALSを有効にし、フロントエンドでcredentials: 'include'を指定
CSRF対策との関係
KurocoではCORS + Content-Type: application/json の組み合わせにより、モダンブラウザにおけるCSRF攻撃を防御: 1. Content-Type: application/json はブラウザのプリフライトリクエストを発生させる 2. プリフライトでCORS設定がチェックされ、未許可オリジンはブロック 3. HTMLフォームでは application/json を送信できないため、攻撃者はバイパス不可
参考ドキュメント
../../kuroco-docs/docs/management/api-list.md- CORS設定テーブル../../kuroco-docs/docs/faq/cors-and-content-type-prevent-csrf-attacks.mdx- CSRF対策の詳細../../kuroco-docs/docs/faq/i-changed-cors-but-it-is-not-reflected.mdx- CORS変更の反映遅延
---
6. 後処理によるレスポンス制限
管理画面: [API] → エンドポイント一覧 → [後処理]
APIのレスポンスから不要なフィールドを除外し、公開情報を制限する機能です。
出力許可リスト(ホワイトリスト)
指定したフィールドのみレスポンスに含めるフィルター:
# 設定例: list内のsubjectとcontents、pageInfoのみ返す
list.subject
list.contents
pageInfo- ネストはドット(
.)区切りで指定 - 配列のインデックス指定は不要(自動処理)
- パフォーマンス向上のため、カスタム処理の前に配置することを推奨
出力変換リスト
フィールドの削除・名称変更・変換関数の適用:
- 利用可能関数: Truncate, Trim, Strtotime, Date Format, Uppercase, Lowercase, Sprintf, Nl2br, FileSize, ImageSize
カスタム処理
Smartyテンプレートでのカスタムロジック適用($json → $processed_json)
参考ドキュメント
../../kuroco-docs/docs/management/api-postprocessing.md- 後処理の設定画面../../kuroco-docs/docs/reference/post-processing.md- 後処理の詳細リファレンス
---
7. プラットフォームセキュリティ
Kurocoプラットフォーム自体が提供するセキュリティ機能:
API
| 機能 | 説明 |
|---|---|
| HTTPS | 全通信を暗号化 |
| TLS証明書 | SSL/TLS証明書の自動管理 |
| WAF | Webアプリケーションファイアウォール |
| CDN | コンテンツ配信ネットワーク |
| DDoS対策 | 分散型サービス拒否攻撃への対策 |
| Fastly DDoS Protection | オプションで高度なDDoS保護 |
| アクセスログ/監査ログ | リクエストの記録・追跡 |
| SAML/OAuth連携 | 外部IdP経由のログイン |
| クライアント証明書 | オプションでのmTLS認証 |
データセンター
- Google Cloud Platform(東京/EU/USリージョン選択可)
- プライベートクラウド版も対応
セキュリティ認証
- ISMS (ISO/IEC 27001:2022)
- ISMSクラウド (ISO/IEC 27017:2015)
- プライバシーマーク
- Assuredセキュリティ評価: 96.6/100(全体上位5%)
脆弱性診断
- コンテナ更新毎の脆弱性スキャン(ほぼ毎日)
- VADDY連携による自動脆弱性診断(管理画面から申込可)
参考ドキュメント
../../kuroco-docs/docs/about/security.md- セキュリティ概要
---
8. 403 Forbiddenエラーのトラブルシューティング
APIから403エラーが返される場合のチェックリスト:
1. IP制限の確認: API → セキュリティ → IPアドレス制限にアクセス元IPが含まれているか 2. エンドポイントの認証要件: Topics::insertなど、一部エンドポイントはログイン状態が前提 3. APIリクエスト制限: GroupAuthまたはMemberCustomSearchAuthで拒否されていないか 4. コンテンツ定義の制限: コンテンツ定義レベルでの閲覧制限を確認 5. CORS設定: フロントエンドのオリジンがCORS_ALLOW_ORIGINSに登録されているか
ログイン必須エンドポイントの回避策
セキュリティ上ログイン必須のエンドポイントをパブリックに使用したい場合:
- api_internal プラグイン: カスタム処理で
member_idを指定してリクエスト - 前処理でのログイン注入:
{login member_id=1 overwrite=false}をエンドポイントの前処理に設定
参考ドキュメント
../../kuroco-docs/docs/faq/the-api-returns-403-forbidden-even-though-no-restrictions-are-applied.mdx
---
9. 管理APIによる設定変更
APIのセキュリティ設定(CORS、IP制限、認証方式など)は管理画面だけでなく、管理API(admin_api)経由でも操作可能です。
/kuroco-admin-apiスキルで管理APIをCLI経由で実行できますdiscoverモードでAPIセキュリティ関連のモデル・メソッドを探索可能- CI/CDパイプラインでの環境構築自動化などに活用できます
Related skills
How it compares
API recipe skill for Kuroco headless CMS—not a generic REST CRUD generator or WordPress skill.
FAQ
Who is kuroco-api-content for?
Developers and small teams integrating Kuroco RCMS for files, images, and bulk news content from scripts or agent-driven codegen.
When should I use kuroco-api-content?
During Build integrations when implementing upload, bulk_upsert, or image URL construction against your Kuroco site API.
Is kuroco-api-content safe to install?
Use the Security Audits panel on this Prism page; treat credentials: include and upload endpoints carefully and never expose session cookies in public repos.