Instagram Graph APIメモ

Instagram Graph APIを使う機会があったので、そのメモ。
なお、Instagram Graph APIはFacebook AppをDevelopment Modeで使用している。（Live Modeではない）
公式サイト：https://developers.facebook.com/docs/instagram-api
API Reference：https://developers.facebook.com/docs/instagram-api/reference

# エンドポイントの整理
例えば、[公式](https://developers.facebook.com/docs/instagram-api/reference/user)には「ユーザーのメタデータを取得」と書いてある（としか書いてない）`GET /{ig-user-id}?fields={fields}`は、{fields}の手前にノード名であるmediaをつける＝`GET /{ig-user-id}?fields=media{fields}`と、そのユーザーのインスタ投稿が一覧形式で返ってくる。単一の投稿の詳細を覗く`GET /{ig-media-id}?fields={fields}`の一覧化と言える。
同じことは別ノードであるinsights等でも指定可能だが、それぞれで必要になるアクセス権が違うので注意。

# until,sinceのパラメータ指定について
[公式の記述](https://developers.facebook.com/docs/graph-api/using-graph-api#time)だと結局何を指定すればいいのかよくわからなかったのだが、要するに「1970年1月1日からの秒」を指定すればいいらしい。
例えば2020/2/7 00:00:00(=1581001200秒)をsinceとする場合、`GET /{ig-user-id}?metric=insights.since(1581001200){engagement,impressions,reach,saved}`となる。(フィールドは適当なので適宜変えてください）

なお、Instagram Graph APIで時間ベースページネイションがサポートされているのは2020年2月時点ではこのinsightsノードのみのようだ。（[このページ](https://developers.facebook.com/docs/instagram-api/overview)の最下部のLimitationの項にその旨が書かれている）
これが残念である。
mediaで使いたい…（ちなみにmediaでsinceパラメータ付けても無視される）

# media_type値について
`GET /{ig-media-id}?fields={fields}`によるメタデータ取得で、fieldsにmedia_typeを指定した場合、レスポンスに対象の投稿のmedia_typeが記述される。(他にもあるかも。あくまで自身の手元で実験した範囲で確認したものです）

|値|内容|
|---|---|
|IMAGE|単一の画像のみの投稿の場合はこれになる|
|VIDEO|単一の動画のみの投稿の場合はこれになる|
|CAROUSEL_ALBUM|複数のメディア(※)の投稿の場合はこれになる|

(※)画像のみ2枚以上、動画のみ2つ以上、画像＋動画、動画＋画像はいずれもCAROUSEL_ALBUMになる

# CAROUSEL_ALBUMの場合のmediaレスポンス
mediaのfieldにchildrenを指定すると、media_type=CAROUSEL_ALBUMのmediaに関しては、一緒に個々の画像のmedia_idがレスポンスとして返却される。
media_type=IMAGE(単一画像) or media_type=VIDEO(単一動画)の場合、fieldsにchildrenを指定しても、レスポンスにchildrenは登場しない。
単一画像の場合のレスポンスサンプルはこれ↓

```json-doc
{
    "media": {
        "data": [
            {
                "caption": "test",
                "media_type": "IMAGE",
            },
         ....
       ]
}
```

複数画像投稿の場合のレスポンスサンプルはこれ↓

```json-doc
{
    "media": {
        "data": [
            {
                "caption": "test",
                "media_type": "CAROUSEL_ALBUM",
                "children": {
                    "data": [
                        {
                            "id": "xxx..."
                        },
                        {
                            "id": "yyy..."
                        }
                    ]
                },
            }
         ....
       ]
}
```

# CAROUSEL_ALBUMのchildrenのmedia objectのメタデータ取得について
CAROUSEL_ALBUMのchildrenに該当するmedia_idに対して、[このページ](https://developers.facebook.com/docs/instagram-api/reference/media#returnable-fields)に「アルバムの子を除く」と書いてある項目（たとえばcaption）をfieldsに指定して`GET /{ig-media-id}?fields={fields}`すると、OAuthExceptionが帰ってきてエラーになる。（別にこのエラーOAuthのエラーでもなんでもないはずだが…なぜかOAuthExceptionなんだそうだ）
例えばcaptionは「アルバムの子を除く」なので、childrenのmedia_idに対して`fields=caption`を指定してAPIを呼び出すとエラー。

一方でmedia_typeはこの対象ではないので、childrenのmedia_idに対しても有効である。
親のmedia_typeはCAROUSEL_ALBUMだが、子のmedia_typeは各々のメディアに相当するtype文字列が返ってくる。
(1)動画＋(2)静止画、というCAROUSEL_ALBUMの場合は、(1)のmedia_typeはVIDEO、(2)のmedia_typeはIMAGEになる。

ただ、最初のメタデータ取得時点ではchildrenのmedia_typeが取得できないため、子の各メディアの詳細情報を取得するためには、一度全体のメタデータを取得したのち、children要素があったら、そのchildren要素の各media_idをもとに、その子の数だけ再度mediaのメタデータ取得を行う必要がある（これが面倒だ。。）

**2020/6/13追記**
``GET /{ig-user-id}/media?id,media_type,children{id,media_url,media_type}``などとすることで子要素のmedia_urlも一緒にとれた。(@regepan@github さんより情報提供いただきました。ありがとうございます)
こんなかんじになります↓

```json-doc
{
    "data": [
        {
            "id": "親mediaのmedia_id",
            "media_type": "CAROUSEL_ALBUM",
            "children": {
                "data": [
                    {
                        "id": "子media1のmedia_id",
                        "media_url": "(子media1のmedia_url)",
                        "media_type": "IMAGE"
                   },
                    {
                        "id": "子media2のmedia_id",
                        "media_url": "(子media2のmedia_url)",
                        "media_type": "VIDEO"
                    }
                ]
            }
        },
        .....
}
```

# プロアカウントになる前のメディアのインサイトがinsightsで取得できない
公式には特別明記がないが、Instagramプロアカウント（Business / Creator）になる前に投稿したmediaに対して`GET /{ig-media-id}/insights?metric={metric}`するとエラーになる。
例えば下記のようなケースである。
2/1　インスタに写真を投稿・・・Aとする
2/5　インスタアカウントをCreatorに変更
2/8　A（のmedia_idで）のinsightsを見る　**→　エラーになる。**

ちなみにこんな↓エラーが返ってくる。

```json-doc
{
    "error": {
        "message": "Invalid parameter",
        "type": "OAuthException",
        "code": 100,
        "error_data": {
            "blame_field_specs": [
                [
                    ""
                ]
            ]
        },
        "error_subcode": 2108006,
        "is_transient": false,
        "error_user_title": "Media Posted Before Business Account Conversion",
        "error_user_msg": "The media was posted before the most recent time that the user's account was converted to a business account from a personal account.",
        "fbtrace_id": "xxxx..."
    }
}
```

ただ、これはあくまでInstagram Graph APIの中だけの話らしくて、スマホのインスタアプリでAを見る分には、Business / Creatorになる前に投稿したmediaのインサイトが見れる。
→実際、見れた。ただ、APIのレスポンスと比較して一致していることを確認したわけではないので（そもそも上記の事情でAPIのレスポンスは確認できない）なんとも言えない。

そういえば、Business / Creatorからそうでないアカウントの切り替えはいつでもできるので、Creator→普通→Creatorと遷移させたときの間の部分までちゃんと厳密に検査するのか…？とふと疑問に思ったが面倒なので深堀しない。。
（なんとなく、「最後の切り替えタイミング以降」しか見てない気がするが）