developer.stockcito.com

開発者ドキュメント

Stockcitoアプリの構築に必要な情報をまとめています。マニフェスト、権限、Public API、UI拡張、自動化、Marketplaceへの公開を実例付きで解説します。

はじめに

Stockcitoアプリとは

アプリとは、任意の言語で動作する外部サービス(お客様自身のサーバー)です。Stockcitoの小売事業者アカウントに接続して、APIで注文や商品を読み取ったり、宣言型コンポーネントでダッシュボードを拡張したり、Stockcito Flowでイベントに自動応答したりできます。

アプリのコードがStockcito内で実行されることはありません。すべてHTTP経由です。Stockcitoからお客様のサービスへ(webhook、UI拡張、Flow actions)呼び出す場合と、お客様のサービスからStockcitoへ(Public API)呼び出す場合があります。インストール時に事業者へ発行されたトークンを使います。リクエストはHMAC署名され、双方のなりすましを防ぎます。

SDKは必須ではありません — HTTPとJSONで連携できます
インストール前に事業者が各権限を確認して承認します
Marketplace掲載前にStockcitoが審査します
無料または買い切り価格を設定できます

利用開始

開発者アカウント

事業者アカウントとは別のアカウントです。インストールする事業者とログイン情報を共有することはありません。

1

開発者アカウントを作成

メールアドレスで /developers に登録します。事業者アカウントとは別です。

2

最初のアプリを登録

名前、説明、カテゴリ、サーバーのベースURL(endpoints.baseUrl)を登録します。

3

マニフェストを作成

アプリの機能を宣言するJSONです。下の「マニフェスト」を参照してください。

4

テストアカウントで確認

Marketplaceの審査に提出する前に、ご自身のテスト用事業者アカウントへインストールします。

開発者ダッシュボードでアプリ一覧と、各インストールの配信状況(webhookの送信結果)を確認できます。事業者の売上や顧客などの業務データは見えません。「インストール #45 への配信 #123 がHTTP 500で失敗」といった情報だけが表示されます。

リファレンス

マニフェスト

アプリの情報、要求する権限、提供する拡張機能を1つのJSONで宣言します。

{
  "key": "acme.puntos",
  "name": "Acme ポイント",
  "description": "購入ポイントプログラム",
  "category": "Crecimiento",
  "version": "1.0.0",
  "author": { "name": "Acme SRL", "url": "https://acme.dev" },
  "roles": ["owner", "admin"],
  "scopes": ["orders:read", "customers:read"],
  "events": ["order.paid"],
  "extensions": {
    "admin": ["dashboard.card"],
    "dna": [{ "key": "loyalty-widget", "name": "ポイントウィジェット" }],
    "automationActions": [{ "key": "add_points", "name": "ポイントを追加" }]
  },
  "endpoints": {
    "baseUrl": "https://acme.dev",
    "webhookPath": "/webhook"
  }
}
keystring

ドットを含む一意の名前空間(例: acme.loyalty)。アプリの固定識別子として使うため、バージョン間で変更しないでください。

categoryenum

現在受け付けるenum値はEscritorio、Comercio、Contenido、Crecimiento、Integraciones、Sistemaです(入力値はスペイン語です)。

rolesstring[]

インストールできる事業者のロール: owner、admin、manager、cajero(レジ担当)。初期設定ではownerのみです。

scopesstring[]

Public APIで使う権限です(Scopesを参照)。インストール前の同意画面にそのまま表示されます。

eventsstring[]

購読するwebhookイベント(order.created、order.paid、order.shipped、order.cancelled、product.published、inventory.low、customer.registered)。

extensions.adminstring[]

事業者Dashboard内で表示するUI拡張: dashboard.card、order.sidebar、product.sidebar、customer.sidebar。

extensions.dnaobject[]

事業者の公開ストア(Studio → ホームデザイン)に追加するモジュールです。

extensions.automationActionsobject[]

事業者が自動化を作成したとき、Stockcito Flowからサーバーへ呼び出すアクションです。

endpoints.baseUrlurl

サーバーのルートURLです。webhook、UI、actionの各パスはこのURLを基準にします。公開HTTPSが必須です。SSRF対策として、StockcitoはプライベートIPやlocalhostを拒否します。

endpoints.webhookPathpath

eventsに宣言したイベントを受信するパスです。初期値は /webhook です。

権限

利用可能なScopes

orders:read注文の参照
orders:write注文の作成・更新
products:read商品の参照
products:write商品の作成・更新
customers:read顧客の参照
customers:write顧客の作成・更新
inventory:read在庫の参照
inventory:write在庫の更新
sales:read売上の参照
sales:write売上の作成・更新
shipping:read配送エリアの参照
shipping:write配送エリアの更新

現在、*:read scopesで下記のPublic APIリソースを参照できます。*:write scopesは将来の利用向けです。事業者はインストール前に同意画面で権限を確認するため、アプリに必要な権限だけを要求してください。

フロー

インストールと同意

事業者が内容を確認せずにアプリをインストールすることはありません。必ず事前に同意画面が表示されます。

事業者は「設定 → アプリ」でマニフェストのURLを入力するか、JSONを直接貼り付けます。Stockcitoが取得・検証し、名前、説明、バージョン、権限をわかりやすく表示します(例: 「注文と顧客を参照できます」)。内容を確認してから承認します。

承認後、Stockcitoはインストールごとに固有のアクセストークンを生成し、一度だけ画面に表示します。事業者(または必要に応じてアプリ)は、このトークンを Authorization: Bearer <token> としてPublic APIに送ります。Stockcitoにはハッシュのみ保存されます。紛失した場合は復元できず、再インストールが必要です。

リファレンス

Public API

アプリをインストールした事業者の業務データを、インストール用トークンで認証して読み取るAPIです。

Base URLurl

https://api.stockcito.com/api/public/v1

Authorizationheader

Bearer <token> — インストール時に発行されたトークンです。

Stockcito-Versionheader

すべてのリクエストで必須です。現在の値: 2026-09。日付ベースのバージョン管理により、既存の連携を壊さず変更できます。

Rate limitlímite

トークンごとに毎分60リクエスト(IP単位ではありません)。一般APIのレート制限とは別です。

利用可能なリソース(すべて読み取り専用、page/perPageでページ分割):

GET /productsproducts:read
GET /customerscustomers:read
GET /salessales:read
GET /inventoryinventory:read
GET /ordersorders:read
GET /returnsorders:read
GET /shippingshipping:read
curl "https://api.stockcito.com/api/public/v1/products?page=1&perPage=20" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Stockcito-Version: 2026-09"

# {"data":[...], "total":123, "page":1, "perPage":20}

リファレンス

UI拡張

HTML、CSS、JavaScriptを書かずに、事業者のDashboard内へ独自のコンテンツを表示できます。

extensions.adminにdashboard.cardを宣言すると、Stockcitoは{baseUrl}/stockcito-ui/dashboard-cardへ署名付きGETを送り、応答を事業者Dashboardのカードとして表示します。HTMLは送信しません。許可された値だけで構成する宣言型ノードツリーを返すため、想定外の内容は挿入できません。

// GET /stockcito-ui/dashboard-cardへの応答例
{
  "type": "card",
  "title": "ポイント残高",
  "children": [
    { "type": "text", "value": "有効ポイント 1,240", "weight": "bold" },
    { "type": "badge", "label": "今週 +80", "tone": "success" },
    { "type": "link", "label": "詳細を見る", "href": "https://acme.dev/panel" }
  ]
}

使用可能なノード: text、badge、link、stack(子要素を縦または横に配置)、card(他のノードを内包)。各階層は最大20個、応答は20KBまでです。サーバー停止、応答遅延、形式不正の場合、Stockcitoはカードだけを非表示にし、Dashboardには影響させません。

各署名付きリクエストにはX-Stockcito-TimestampとX-Stockcito-Signature: sha256=...が含まれます。署名は署名キー、timestamp、ピリオド、pathから計算したHMAC-SHA256です。サーバー側で検証し、リプレイ攻撃防止のため、現在時刻から5分以上離れたtimestampを拒否してください。

Node/Expressで署名を検証する例:

const crypto = require("crypto")

const SIGNING_KEY = process.env.STOCKCITO_SIGNING_KEY // インストール時にStockcitoから発行
const TOLERANCE_SECONDS = 300

app.get("/stockcito-ui/dashboard-card", (req, res) => {
  const timestamp = req.header("X-Stockcito-Timestamp")
  const signatureHeader = req.header("X-Stockcito-Signature") || ""
  const path = req.path // "/stockcito-ui/dashboard-card"

  const now = Math.floor(Date.now() / 1000)
  if (!timestamp || Math.abs(now - Number(timestamp)) > TOLERANCE_SECONDS) {
    return res.status(401).send("timestampが無効または期限切れです")
  }

  const expected = crypto
    .createHmac("sha256", SIGNING_KEY)
    .update(`${timestamp}.${path}`)
    .digest("hex")

  // timingSafeEqualでタイミング攻撃を防ぎます。
  
  const received = signatureHeader.replace("sha256=", "")
  const valid =
    received.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected))

  if (!valid) return res.status(401).send("署名が無効です")

  res.json({
    type: "card",
    title: "ポイント残高",
    children: [{ type: "text", value: "有効ポイント 1,240", weight: "bold" }],
  })
})

リファレンス

DNA Modules

Studioから、アプリが提供するモジュールを事業者の公開ストアに追加できます。

extensions.dnaで、各モジュールの固定keyと表示名を宣言します。事業者はStudio → ホームデザインで追加するモジュールを選びます。Stockcitoは同じ署名付きUIプロトコルを使い、{baseUrl}/stockcito-ui/dna/{key}から内容を取得します。許可されたノード形式を検証し、事業者ごとに60秒間キャッシュします。公開ストアの訪問者にモジュールが表示されますが、アプリがストアやデータベースへ直接アクセスすることはありません。

GET https://acme.dev/stockcito-ui/dna/reviews-widget · X-Stockcito-Timestamp · X-Stockcito-Signature

リファレンス

Flow Actions

事業者がFlow自動化から自動実行できるアクションです。

extensions.automationActionsの各アクションは、事業者が「Xが起きたらYを実行」のようなルールを作ると利用できます。実行時にStockcitoはイベントデータをbodyに入れ、{baseUrl}/stockcito-actions/{actionKey}へ署名付きPOSTを送信します。

POST /stockcito-actions/add_points
Content-Type: application/json
X-Stockcito-Timestamp: 1735689600
X-Stockcito-Signature: sha256=<署名キーでbodyをHMAC>

{ "orderId": 4821, "total": 15400, "customerId": 92 }

UI拡張と同様に署名を検証しますが、ここではtimestamp、ピリオド、body(パスではなくJSON全体)がHMACの対象です。成功時はHTTP 2xxを返します。一時的なHTTP 4xx/5xx(サーバーの一時停止など)はbackoff付きで再試行されます。恒久的な失敗を検出した場合に2xxを返さないでください。Stockcitoは成功として扱います。

Nodeだけで動く最小構成のサーバー例: actionを受信し、bodyの署名を検証して応答します。

const http = require("http")
const crypto = require("crypto")

const SIGNING_KEY = process.env.STOCKCITO_SIGNING_KEY

http.createServer((req, res) => {
  if (req.method !== "POST" || req.url !== "/stockcito-actions/add_points") {
    res.writeHead(404).end()
    return
  }

  let body = ""
  req.on("data", (chunk) => { body += chunk })
  req.on("end", () => {
    const timestamp = req.headers["x-stockcito-timestamp"]
    const received = (req.headers["x-stockcito-signature"] || "").replace("sha256=", "")

    const expected = crypto
      .createHmac("sha256", SIGNING_KEY)
      .update(`${timestamp}.${body}`)
      .digest("hex")

    if (received.length !== expected.length || !crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected))) {
      res.writeHead(401).end("署名が無効です")
      return
    }

    const { orderId, total, customerId } = JSON.parse(body)
    // ポイント加算、配送作成などの処理をここに記述します。
    console.log(`注文 ${orderId} / 顧客 ${customerId} / 合計 $${total}`)

    res.writeHead(200, { "Content-Type": "application/json" })
    res.end(JSON.stringify({ ok: true }))
  })
}).listen(3000)

公開

Marketplace

事業者が安心してアプリを見つけ、インストールできるように公開します。

1

審査に提出

/developersでアプリを新規登録・更新すると「審査待ち」になります。自動で公開されることはありません。

2

Stockcitoが審査

申告された機能とマニフェストが一致するか確認します。理由を添えて差し戻す場合があります。

3

承認済みスナップショットを公開

インストールされるのは承認済みのバージョン(approvedManifest)です。審査中のdraftが既存のインストールに置き換わることはありません。

4

価格を設定(任意)

無料、またはMercado Pago Connectによるインストール時の買い切り価格を設定できます。現在、アプリの継続課金には対応していません。

/developersからご自身のMercado Pagoアカウントを接続すると、アプリに価格を設定できます。事業者のストア決済と同じOAuthフローを開発者として利用します。購入代金はご自身のMercado Pagoトークンに請求され、Stockcitoはプラットフォーム手数料を受け取ります。決済webhookで入金が確認されるまでアプリは無効です。

ツール

TypeScript SDK

初期版のTypeScript SDK(packages/sdk-ts)はPublic APIリソースの型を提供します。npmなどの公開レジストリにはまだ公開されていません。現時点でサポートされる連携方法は、上記のHTTP + JSONです。どの言語からでも利用できます。

セキュリティの基本

セキュリティ

公開HTTPSが必須

endpoints.baseUrlは公開IPへ解決される必要があります。Stockcitoはlocalhost、プライベートIP(10.x、192.168.xなど)、リダイレクトを拒否し、内部ネットワークのサービスを呼び出しません。

署名を必ず検証

発行された署名キーを使ってX-Stockcito-Signatureを検証する前に、webhook、UI fetch、Flow actionを処理しないでください。

古いtimestampを拒否

現在時刻から5分以上離れたtimestampはリプレイの可能性があります。署名が正しくても拒否してください。

アクセストークンを秘密にする

Public APIのインストールトークンは、その事業者データに対するパスワードと同等です。データベース認証情報と同じように保護してください。

サポート

よくある質問

事業者はMarketplace経由でアプリを入手する必要がありますか?▼

いいえ。マニフェストURLまたはJSONを直接入力すれば、Marketplace審査なしでインストールできます。Marketplaceは、Stockcitoの審査済みアプリを知らない事業者にも見つけてもらうための場所です。

インストール済みのアプリに影響せずマニフェストを変更できますか?▼

はい。更新版を提出し、新しい審査に合格するまでは、既存のインストールは承認済みバージョンを使い続けます。

テスト用の事業者はどうすればアプリを試せますか?▼

マニフェストを直接貼り付けてインストールします。自分のテストアカウントで試すためにMarketplaceの承認を待つ必要はありません。

Stockcitoからの呼び出し時にサーバーが停止していたら?▼

UI拡張とDNA Modulesは非表示になるだけで、事業者側の画面には影響しません。Flow Actionsとwebhookは、最終的に失敗と判定するまで指数backoffで再試行します。

開発者ダッシュボードを開く