# エラー

標準のエラーレスポンス形式とAPIのHTTPステータスコード。

Source: https://support.toolingmetrics.com/ja/api/errors/
Updated: 2026-10-23

ほとんどのAPIエラーは、`errors`配列を含むJSON本文を返します。例外があるため、汎用パーサーを作成する前に、下記の`404`の注意事項を確認してください。

<a id="error-response-format"></a>

## エラーレスポンスの形式

```json
{
  "errors": ["Description of what went wrong"]
}
```

書込みの検証エラーでは、失敗した項目ごとに1つのメッセージが配列に入ります。

```json
{
  "errors": [
    "Name can't be blank",
    "Quantity must be greater than 0"
  ]
}
```

<a id="the-404-exception"></a>

### `404`の例外

IDが存在しない、または別の組織に属する場合の「レコードが見つからない」レスポンスは、各コントローラのrescue処理で明示的に発生します。ほかのエラーの`errors`配列ではなく、文字列を値とする**単数形**の`error`キーを使います。

```json
{
  "error": "Couldn't find Part with 'id'=999"
}
```

`body.errors`だけを確認すると、`404`を見落とします。最初にステータスを確認し、`404`の本文を読むときはキーによって処理を分けてください。

<a id="http-status-codes"></a>

## HTTPステータスコード

| ステータス | 意味 | 主な原因 |
|---|---|---|
| `200 OK` | リクエスト成功 | GET、PATCH |
| `201 Created` | リソース作成 | POST |
| `204 No Content` | リソース削除 | DELETE |
| `401 Unauthorized` | トークンが未指定・無効、**または**有効でも操作権限がない | どちらも同じステータス。[認証](https://support.toolingmetrics.com/ja/api/authentication/)で区別する方法を確認してください。存在しない`organization_id`も、アクセスできない組織と同じく権限不足になります。このAPIに`403`はありません。 |
| `404 Not Found` | リソースが見つからない | IDが誤っている、または別の組織に属する。本文は単数形の`error`キー。上記を参照。 |
| `422 Unprocessable Entity` | 検証失敗 | 必須項目の未指定、無効な値。 |
| `429 Too Many Requests` | レート制限超過 | [レート制限](https://support.toolingmetrics.com/ja/api/rate-limits/)を参照。 |

不正なJSONや予期しないサーバーエラーによって`400 Bad Request`や`500 Internal Server Error`になる場合がありますが、APIコントローラは明示的に処理していません。本文が上記の`errors`または`error`形式とは限りません。

<a id="handling-errors"></a>

## エラーの処理

```python
import requests

response = requests.get(
    "https://api.toolingmetrics.com/v1/organizations/12/machines",
    headers={"Authorization": "Bearer YOUR_TOKEN"}
)

if response.status_code == 401:
    print("Check your API token, or your role for this resource")
elif response.status_code == 404:
    print("Not found:", response.json().get("error"))
elif response.status_code == 429:
    retry_after = response.headers.get("Retry-After", 60)
    print(f"Rate limited. Retry after {retry_after} seconds.")
elif not response.ok:
    errors = response.json().get("errors", [])
    print("API error:", errors)
else:
    data = response.json()
```
