HERE Destination Weather APIを叩いてみたら403エラーでハマった話

これは [【HERE WeGo!】ジオファン集まれ！地理空間情報、地図に関する記事を募集しています by HERE Advent Calendar 2022](https://qiita.com/advent-calendar/2022/here)　19日目の記事です。

# はじめに
hereのサービスにはたくさんのAPIが提供されています。その中でも[「HERE Destination Weather API」](https://developer.here.com/documentation/destination-weather/dev_guide/topics/guide.html)という天気予報情報を取得するのAPIが気になったので試していました。中でも位置情報から[月の満ち欠けの情報](https://developer.here.com/documentation/destination-weather/dev_guide/topics/example-astronomy-forecast.html)を取得できることにとても興味をもったので、このAPIを使い、Mapbox GL JSで月の満ち欠けを表示するマップを作っていました。

このようなマップが出来上がる予定でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1575765/b13a6b28-eb2a-8b83-00ca-a6d6764166a3.png)


地図をクリックするとピンが表示され、その地点の７日間先の月の満ち欠け情報を画面上部に表示するというマップです。月の満ち欠けはCSSで表現しており、[こちらのコードペンの作品](https://codepen.io/shamir/pen/YGbbNX)を参考にしました。

[こちらのページ](https://developer.here.com/documentation/examples/rest/auto_weather/weather-observation-lat-long)でブラウザからHERE Destination Weather APIへのリクエストを試すことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1575765/a328f2f8-4f4c-75a8-b878-c024367eacb1.png)


次のリクエストで、緯度経度情報から７日間の天文予報が取得できる予定でした。
```shell
https://weather.ls.hereapi.com/weather/1.0/report.json?product=forecast_astronomy&latitude=43.064&longitude=141.361&oneobservation=true&apiKey={API_KEY}
```
結果は北海道北三条の７日間の天文予報を取得できます。
```json
{
  "astronomy": {
    "astronomy": [
      {
        "sunrise": "7:03AM",
        "sunset": "4:03PM",
        "moonrise": "8:05AM",
        "moonset": "4:35PM",
        "moonPhase": 0.006,
        "moonPhaseDesc": "New moon",
        "iconName": "cw_new_moon",
        "city": "Sapporo",
        "latitude": 43.06,
        "longitude": 141.37,
        "utcTime": "2022-12-24T00:00:00.000+09:00"
      },
      {
        "sunrise": "7:04AM",
        "sunset": "4:04PM",
        "moonrise": "9:03AM",
        "moonset": "5:54PM",
        "moonPhase": 0.039,
        "moonPhaseDesc": "Waxing crescent",
        "iconName": "cw_waxing_crescent",
        "city": "Sapporo",
        "latitude": 43.06,
        "longitude": 141.37,
        "utcTime": "2022-12-25T00:00:00.000+09:00"
      },
      {
        "sunrise": "7:04AM",
        "sunset": "4:04PM",
        "moonrise": "9:48AM",
        "moonset": "7:16PM",
        "moonPhase": 0.099,
        "moonPhaseDesc": "Waxing crescent",
        "iconName": "cw_waxing_crescent",
        "city": "Sapporo",
        "latitude": 43.06,
        "longitude": 141.37,
        "utcTime": "2022-12-26T00:00:00.000+09:00"
      },
      {
        "sunrise": "7:04AM",
        "sunset": "4:05PM",
        "moonrise": "10:22AM",
        "moonset": "8:36PM",
        "moonPhase": 0.181,
        "moonPhaseDesc": "Waxing crescent",
        "iconName": "cw_waxing_crescent",
        "city": "Sapporo",
        "latitude": 43.06,
        "longitude": 141.37,
        "utcTime": "2022-12-27T00:00:00.000+09:00"
      },
      {
        "sunrise": "7:05AM",
        "sunset": "4:06PM",
        "moonrise": "10:50AM",
        "moonset": "9:53PM",
        "moonPhase": 0.279,
        "moonPhaseDesc": "Waxing crescent",
        "iconName": "cw_waxing_crescent",
        "city": "Sapporo",
        "latitude": 43.06,
        "longitude": 141.37,
        "utcTime": "2022-12-28T00:00:00.000+09:00"
      },
      {
        "sunrise": "7:05AM",
        "sunset": "4:07PM",
        "moonrise": "11:13AM",
        "moonset": "11:06PM",
        "moonPhase": 0.385,
        "moonPhaseDesc": "Waxing crescent",
        "iconName": "cw_waxing_crescent",
        "city": "Sapporo",
        "latitude": 43.06,
        "longitude": 141.37,
        "utcTime": "2022-12-29T00:00:00.000+09:00"
      },
      {
        "sunrise": "7:05AM",
        "sunset": "4:07PM",
        "moonrise": "11:35AM",
        "moonset": "*",
        "moonPhase": 0.494,
        "moonPhaseDesc": "First Quarter",
        "iconName": "cw_first_qtr",
        "city": "Sapporo",
        "latitude": 43.06,
        "longitude": 141.37,
        "utcTime": "2022-12-30T00:00:00.000+09:00"
      },
      {
        "sunrise": "7:05AM",
        "sunset": "4:08PM",
        "moonrise": "11:56AM",
        "moonset": "12:16AM",
        "moonPhase": 0.6,
        "moonPhaseDesc": "Waxing gibbous",
        "iconName": "cw_waxing_gibbous",
        "city": "Sapporo",
        "latitude": 43.06,
        "longitude": 141.37,
        "utcTime": "2022-12-31T00:00:00.000+09:00"
      }
    ],
    "country": "Japan",
    "state": "Hokkaidō",
    "city": "Kita-sanjō",
    "latitude": 43.06667,
    "longitude": 141.36667,
    "timezone": 9
  },
  "feedCreation": "2022-12-24T13:20:43.279Z",
  "metric": true
}
```

[APIリファレンス](https://developer.here.com/documentation/destination-weather/dev_guide/topics/resource-type-astronomy-items.html)によると`moonPhase`が月の満ち欠けの数値を表していて、`moonPhaseDesc`の値が月の種類の名称を示しています。

リクエストの結果の数値を調べてみると`moonPhase`は１から-1の間の数値が返され、その数値によって`moonPhase`の情報が変動するみたいです。数値が0に近いほど「New moon（新月）」となり、`moonPhase`の数値が１に近いほど「Full Moon（新月）」となるようです。

月の種類別の英名は下の画像を参考にしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1575765/02793186-b4d1-ee3b-863e-ff118ee3e284.png)
画像出典:[「英会話ライフ」](https://eigo-life.net/knowledge/moon/)



# 403エラーでリクエストが成功しなかった
ブラウザのテストで取得したサンプルデータをもとに動作を確認しながら一通りマップを作成し、いざAPIを叩いたらまさかの403エラーで権限がないぞと怒られてしまいました。
なぜだろうと思い[ドキュメント](https://developer.here.com/documentation/destination-weather/dev_guide/topics/request-constructing.html)を確認するとリクエスト時にAPIキー以外に[OAuthトークン](https://developer.here.com/documentation/identity-access-management/dev_guide/topics/plat-token.html)が必要だとのこと（この時、APIのドキュメントはしっかりと読むべきという教訓を得ました）。

私のようなひよっこエンジニアにとってはなんじゃそりゃ？思うキーワードではありましたが、OAuthトークンを取得するチュートリアルもちゃんと用意されていました。こちらの[Postmanを使ったチュートリアル](https://developer.here.com/documentation/identity-access-management/dev_guide/topics/postman.html)が一番わかりやすいと思います。

このチュートリアルでは、OAuthトークンを取得して[「HERE Map Tile API」](https://developer.here.com/documentation/map-tile/dev_guide/topics/introduction.html)というマップタイルの画像を取得できるAPIを使い、OAuthトークンを使用してリクエストするところまで紹介されています。
こちらのAPIは私の環境でも問題なくリクエストに成功したので、使用しているOAuthトークンが有効なものであるというのは確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1575765/a77ac673-0e0f-7bbc-6f2c-c0393bbe122d.png)

APIキーも他のAPIを試してリクエストに成功したので、APIキーが有効であることも確認できました。下記の画像は[「HERE Geocoding & Search API」](https://developer.here.com/documentation/geocoding-search-api/dev_guide/index.html)をPostmanで試した様子です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1575765/1700f421-2769-30a7-3f61-e3a360c27a98.png)





しかし、このAPIキーとOAuthトークンを使用してPostmanで「HERE Destination Weather API」を叩いても403エラーが返ってくる結果となってしまいました。

下記の画像のようにhereのブロジェクトマネージャーからサービスをリンクする設定も行いましたがうまくいきませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1575765/2ec98118-f8ee-7c1d-57e4-3ed23e1507a1.png)

# 追記　公式ドキュメントの情報が古かった
[こちらのサービス一覧](https://platform.here.com/services/)（ログイン必須）のページからAPIの最新のドキュメントが記載されておりました。

### サービス一覧ページから「HERE Destination Weather v3」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1575765/5589eb64-a81f-9f50-b4c1-6068327701b8.png)

### 「API参照」のタブをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1575765/6d19497f-3114-80d1-a806-8d74e4d6b113.png)

### これだー！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1575765/a3e8f578-c6ae-f09e-e4c9-5bad5ce519e9.png)


ベースURLがそもそも違ってました。OAuthトークンも必要ないみたいです。

下記のリクエストで無事に200が返ってきました。
```
https://weather.hereapi.com/v3/report?products=forecastAstronomy&location=43.064,141.361&apiKey={API_KEY}
```

結果はこんな感じです。
```json
{
  "places": [
    {
      "astronomyForecasts": [
        {
          "place": {
            "address": {
              "countryCode": "JPN",
              "countryName": "Japan",
              "state": "Hokkaidō",
              "city": "Kita-sanjō"
            },
            "location": {
              "lat": 43.06667,
              "lng": 141.36667
            }
          },
          "forecasts": [
            {
              "sunRise": "07:04:00",
              "sunSet": "16:21:00",
              "moonRise": "22:26:00",
              "moonSet": "10:19:00",
              "moonPhase": "-0.703",
              "moonPhaseDescription": "Waning gibbous",
              "iconName": "cw_waning_gibbous",
              "time": "2023-01-13T00:00:00.000+09:00"
            },
            {
              "sunRise": "07:04:00",
              "sunSet": "16:23:00",
              "moonRise": "23:32:00",
              "moonSet": "10:38:00",
              "moonPhase": "-0.610",
              "moonPhaseDescription": "Waning gibbous",
              "iconName": "cw_waning_gibbous",
              "time": "2023-01-14T00:00:00.000+09:00"
            },
            {
              "sunRise": "07:03:00",
              "sunSet": "16:24:00",
              "moonSet": "10:58:00",
              "moonPhase": "-0.509",
              "moonPhaseDescription": "Last Quarter",
              "iconName": "cw_last_quarter",
              "time": "2023-01-15T00:00:00.000+09:00"
            },
            {
              "sunRise": "07:03:00",
              "sunSet": "16:25:00",
              "moonRise": "00:39:00",
              "moonSet": "11:21:00",
              "moonPhase": "-0.406",
              "moonPhaseDescription": "Last Quarter",
              "iconName": "cw_last_quarter",
              "time": "2023-01-16T00:00:00.000+09:00"
            },
            {
              "sunRise": "07:02:00",
              "sunSet": "16:26:00",
              "moonRise": "01:51:00",
              "moonSet": "11:48:00",
              "moonPhase": "-0.302",
              "moonPhaseDescription": "Waning crescent",
              "iconName": "cw_waning_crescent",
              "time": "2023-01-17T00:00:00.000+09:00"
            },
            {
              "sunRise": "07:02:00",
              "sunSet": "16:27:00",
              "moonRise": "03:07:00",
              "moonSet": "12:23:00",
              "moonPhase": "-0.205",
              "moonPhaseDescription": "Waning crescent",
              "iconName": "cw_waning_crescent",
              "time": "2023-01-18T00:00:00.000+09:00"
            },
            {
              "sunRise": "07:01:00",
              "sunSet": "16:29:00",
              "moonRise": "04:25:00",
              "moonSet": "13:09:00",
              "moonPhase": "-0.120",
              "moonPhaseDescription": "Waning crescent",
              "iconName": "cw_waning_crescent",
              "time": "2023-01-19T00:00:00.000+09:00"
            },
            {
              "sunRise": "07:00:00",
              "sunSet": "16:30:00",
              "moonRise": "05:40:00",
              "moonSet": "14:08:00",
              "moonPhase": "-0.054",
              "moonPhaseDescription": "Waning crescent",
              "iconName": "cw_waning_crescent",
              "time": "2023-01-20T00:00:00.000+09:00"
            }
          ]
        }
      ]
    }
  ]
}
```

`moonPhaseDesc`だったのが`moonPhaseDescription`になってますね。