福岡市の公開データをFIWARE APIで取得してみよう!

0. はじめに:福岡市データ連携基盤と申請方法

福岡市データ連携基盤とは?

「福岡市データ連携基盤」は、福岡市がスマートシティ化に向けて構築した、行政や民間の様々な分野のデータを横断して共有・活用できる仕組み(都市OS)です。EUを中心に世界中のスマートシティで採用されているオープンソース「FIWARE(ファイウェア)」をベースにしており、屋台情報、区役所のリアルタイム混雑状況、人口統計、キッチンカーなど、幅広いデータがWeb API(NGSI v2規格)を通じて公開されています。

APIアクセスの利用申請方法

このデータ連携基盤のAPIを使って開発を行うには、事前に利用申請を行い、認証用の「アクセストークン」を発行してもらう必要があります。手続きはすべてオンラインで完結し、数日程度で利用可能になります。

STEP 1

利用申請書の作成

「BODIK ODCS(福岡市)」のサイトから「福岡市データ連携基盤利用登録申請書」をダウンロードし、必要事項を記入します。

STEP 2

オンライン申請の送信

福岡市のオンライン申請システム(グラファー)の専用フォームから、作成した申請書を添付して送信します。アカウントなしでもメール認証だけで申請可能です。

STEP 3

トークンとドキュメントの受取

申請が承認されると、数日以内にAPIアクセスに必要な「アクセストークン(WSO2)」と詳細な仕様書が送られてきます。準備はこれで完了です!

それでは、手元にトークンが用意できた前提で、具体的なAPIの仕組みと使い方を見ていきましょう。

1. FIWAREって何?普通のAPIと何が違うの?

FIWAREは、スマートシティ向けのオープンソース基盤です。EU主導で開発され、世界中の自治体・行政がIoTデータや都市データを管理するために採用しています。その中心となるのが Context Broker(Orion)というサーバーで、「今この瞬間の状態」を管理することが得意です。

普通のREST APIと比べて何が違うのか、ざっくりまとめると:

普通のREST API

「リソース」単位でエンドポイントが決まる。例:/users/products。設計はサービスごとに自由。

NGSI v2というのはFIWAREが採用しているAPIの仕様名です。エンドポイントの形や必須ヘッダーが規格で決まっているので、一度覚えれば世界中のFIWARE対応システムで同じ知識が使えます。

ポイント: FIWAREでは「エンティティ」「タイプ」「属性」という3つの概念を覚えればOKです。エンティティ=データの1件、タイプ=データの種類、属性=各フィールドのことです。

2. 福岡市の連携基盤の構成を理解する

福岡市のシステムは、Orionの前にWSO2 API Managerというゲートウェイが立っています。クライアント(あなたのコード)は直接Orionに触れず、必ずゲートウェイ経由でアクセスします。

あなたのコード(curl / Python)
WSO2 API Manager ゲートウェイapi-drk.city.fukuoka.lg.jp
↓ 認証済みリクエストのみ転送
FIWARE Orion 本体(直接アクセス不可)pf-drk.city.fukuoka.lg.jp → 403エラー
注意: ドキュメントに pf-drk.city.fukuoka.lg.jp というURLが書かれていることがありますが、これは内部のOrion本体のアドレスです。実際のアクセス先は api-drk.city.fukuoka.lg.jp です。間違えると403エラーになります。

3. アクセスの準備(認証・必須ヘッダー)

APIのベースURL

endpoint
https://www.api-drk.city.fukuoka.lg.jp/orion/v2.0

必須HTTPヘッダー3点セット

FIWAREのAPIには、普通のAPIにはない特有のヘッダーが必要です。この3つが揃わないとデータが取得できません。

ヘッダー名説明
AuthorizationBearer <TOKEN>WSO2発行のアクセストークン
Fiware-Serviceyatai などテナント名。データの種類によって変わる
Fiware-ServicePath/#データの格納パス。#は全パス対象のワイルドカード
Fiware-Serviceを省略すると0件になります。 エラーにならずに空配列 [] が返ってくるだけなので、原因に気づきにくいです。必ず指定してください。

4. 実際にアクセスしてみる(curl編)

エンティティタイプの一覧を確認する

まず、どんな種類のデータがあるか確認しましょう。

bash / curl
curl -s \
  -H "Authorization: Bearer <YOUR_TOKEN>" \
  -H "Fiware-Service: yatai" \
  -H "Fiware-ServicePath: /#" \
  "https://www.api-drk.city.fukuoka.lg.jp/orion/v2.0/types?options=values"
レスポンス例
["LightCode", "population", "yataiBasedata", "yataiBasedataTest"]

屋台情報を5件取得する

bash / curl
curl -s \
  -H "Authorization: Bearer <YOUR_TOKEN>" \
  -H "Fiware-Service: yatai" \
  -H "Fiware-ServicePath: /#" \
  "https://www.api-drk.city.fukuoka.lg.jp/orion/v2.0/entities\
?type=yataiBasedata&limit=5&options=count,keyValues"
レスポンス例(一部)
[
  {
    "id": "fcod.yataiBasedata.401307.1778688143.97664.00000001",
    "type": "yataiBasedata",
    "name": "寅政",
    "area": "東区",
    "category": "ラーメン/焼きラーメン/焼き鳥/おでん",
    "businessHours": "19:00~3:00",
    "yataiAddress": "〒813-0044 福岡県福岡市東区千早5-9"
  }
]
options=keyValues とは? FIWAREのデフォルトレスポンスは各属性に "value""type""metadata" が付いた冗長な形式です。keyValues オプションを指定すると、シンプルなキー=値形式になって扱いやすくなります。

件数の確認とページネーション

データが多い場合は limitoffset でページを送ります。また options=count を付けると、レスポンスヘッダーに総件数が入ります。

bash / curl(ページネーション)
# 1ページ目(1~100件)
curl -s ... "...?type=yataiBasedata&limit=100&offset=0&options=keyValues"

# 2ページ目(101~200件)
curl -s ... "...?type=yataiBasedata&limit=100&offset=100&options=keyValues"
総件数の確認(レスポンスヘッダーを見る)
curl -s -I \
  -H "Authorization: Bearer <YOUR_TOKEN>" \
  -H "Fiware-Service: yatai" \
  -H "Fiware-ServicePath: /#" \
  "https://www.api-drk.city.fukuoka.lg.jp/orion/v2.0/entities\
?type=yataiBasedata&limit=1&options=count"

# レスポンスヘッダーに以下が含まれる
# Fiware-Total-Count: 107

5. Pythonで取得してみる

Python(requests)— 全件取得
import requests

API_BASE = "https://www.api-drk.city.fukuoka.lg.jp/orion/v2.0"
TOKEN    = "<YOUR_TOKEN>"

def get_headers(service, path="/#"):
    return {
        "Authorization":      f"Bearer {TOKEN}",
        "Accept":             "application/json",
        "Fiware-Service":     service,
        "Fiware-ServicePath": path,
    }

def fetch_all(entity_type, service="yatai"):
    """全件をページネーションで取得する"""
    results = []
    limit   = 100

    # まず総件数を確認
    r = requests.get(
        f"{API_BASE}/entities",
        headers=get_headers(service),
        params={"type": entity_type, "limit": 1, "options": "count,keyValues"},
        timeout=30,
    )
    r.raise_for_status()
    total = int(r.headers.get("Fiware-Total-Count", 0))
    print(f"総件数: {total}")

    # ページネーションで全件取得
    for offset in range(0, total, limit):
        r = requests.get(
            f"{API_BASE}/entities",
            headers=get_headers(service),
            params={
                "type":    entity_type,
                "limit":   limit,
                "offset":  offset,
                "options": "keyValues",
            },
            timeout=30,
        )
        r.raise_for_status()
        results.extend(r.json())
        print(f"  取得: {offset + 1}~{min(offset + limit, total)} 件")

    return results

# 屋台情報を全件取得
yatai_list = fetch_all("yataiBasedata", service="yatai")
print(f"\n取得完了: {len(yatai_list)} 件")

リアルタイム混雑情報を取得する例

Python(AIカメラ混雑情報)
def get_congestion():
    """区役所の現在の混雑状況を取得"""
    r = requests.get(
        f"{API_BASE}/entities",
        headers=get_headers("aicamera", path="/"),
        params={"type": "CongestionInfo", "limit": 17, "options": "keyValues"},
        timeout=30,
    )
    r.raise_for_status()
    data = r.json()

    for cam in data:
        count     = cam.get("count", 0)
        threshold = cam.get("threshold", [10, 20])
        if count < threshold[0]:
            status = "空いている"
        elif count < threshold[1]:
            status = "普通"
        else:
            status = "混雑"
        print(f"{cam['name']}: {count}人 → {status}")

get_congestion()

6. 利用できるデータ一覧(2026-05-18時点)

Fiware-Serviceエンティティタイプ件数更新頻度
yataiyataiBasedata107件随時
yataiLightCode90件随時
fcodpopulation(各区分)約34,000件月次
fcodwaterSpot34件随時
fdcfoodTruckData42件随時
aicameraCongestionInfo17件リアルタイム
people_flowPeopleFlow18件月次

7. ハマりやすいポイント6選

  • 1 Fiware-Serviceを指定し忘れる
    省略してもエラーにならず、空配列 [] が返ってくるだけ。「データが存在しない」と勘違いしやすい。アクセスするデータに対応したサービス名(yatai / fcod / aicamera など)を必ず指定する。
  • 2 ServicePathのワイルドカードを * にする
    NGSI v2のワイルドカードは # であり、* は400エラー(IllegalCharacter)になる。Fiware-ServicePath: /# が正解。
  • 3 アクセス先のドメインを間違える
    ドキュメントや資料に内部URLの pf-drk ドメインが書かれていることがある。実際に接続できるのは api-drk ドメイン(ゲートウェイ)のみ。pf-drk に直接アクセスすると403になる。
  • 4 存在しないエンティティタイプを指定する
    定義書に書かれている yataiStatus はOrion上に存在しない(データ未登録)。実際に存在するタイプは /types エンドポイントで事前に確認しておくのがおすすめ。
  • 5 全件取得時にlimitの上限に気づかない
    limit を指定しないとデフォルトで20件しか返らない。options=count でレスポンスヘッダーに総件数を出力し、offset でページネーションする設計が必要。
  • 6 NGSI v1エンドポイントにアクセスしようとする
    /orion/v1/ への接続は発行されたトークンでは403になる。このシステムで使えるのは /orion/v2.0/ のみ。

FIWAREはとっつきにくい印象がありますが、「エンティティ=データの1件」という概念と、3点セットのHTTPヘッダーさえ理解すれば、あとは普通のREST APIと同じように操作できます。

福岡市の場合は屋台・人口統計・AIカメラ混雑情報・キッチンカー・給水スポットなど幅広いデータが6万件以上公開されています。特にAIカメラ混雑情報はリアルタイムで更新されているので、混雑可視化アプリや通知システムなど面白い活用が期待できます。

次のステップ: 取得したデータをもとに、地図上に屋台をプロットするWebアプリや、区役所の混雑をLINE通知するBotなどを作ってみましょう。データはもう揃っています。