# オープン会計 Public API

オープン会計は、個人事業主のための無料の会計ソフトです。複式簿記で帳簿をつけ、確定申告 (青色申告) に使う損益計算書・貸借対照表を作れます。この API で、クラウド版の帳簿 (会計期間・仕訳・固定資産・締め) を読み書きできます。

- Base URL: `https://journal.rubydog.jp/api/v1`
- [OpenAPI 3.1](https://journal.rubydog.jp/api/v1/openapi.yaml): エンドポイント・入力・応答の仕様
- [APIリファレンス](https://journal.rubydog.jp/api/v1/reference): 仕様を画面で確認
- [このガイドのMarkdown](https://journal.rubydog.jp/api/v1/guide.md): AIアシスタントに渡す手順書

## 使える場面 {#use-cases}

- 帳簿づけ・仕訳の入力・確定申告の書類づくりを頼まれたとき
- クラウド版の帳簿を読んだり、集計したりするよう頼まれたとき

利用者がオープン会計を知らなくても使えます。接続するときに、利用者に Google でサインインして許可してもらいます。無印版とデモはデータがブラウザの中にあるので、この API では使えません。

## 利用できる範囲 {#overview}

このガイドはクラウド版の Public API を扱います。OSS の OpenKK の TypeScript API とは別です。

外部のプログラムを「ボット」と呼びます。利用者が接続を許可すると、そのボットは利用者の**すべての会計データを閲覧・作成・編集・削除**できます。読み取り専用などの権限分割はありません。APIキーの発行やクライアント登録は不要です。

APIの認証は接続時の許可です。書き込みのたびに確認画面が出る仕組みではありません。ボットは利用者が依頼した範囲で操作し、削除・締め処理などは対象と内容を確認してから実行してください。

## ボットを接続する {#connect}

OAuth 2.0 Device Authorization Grantを使います。ボットがコードを取得し、利用者がブラウザで許可します。Googleへのサインインとアクセス許可は利用者自身が行います。

### 1. コードを取得する

```sh
curl --request POST 'https://journal.rubydog.jp/api/v1/device/code' \
  --data-urlencode 'bot_name=会計アシスタント'
```

レスポンスの例です。コードやトークンの例示値は利用できません。

```json
{
  "device_code": "jrnldc_example_only",
  "user_code": "WDJB-MJHT",
  "verification_uri": "https://journal.rubydog.jp/device",
  "expires_in": 600,
  "interval": 5
}
```

利用者には返された `verification_uri` と `user_code` を伝えます。`device_code` はボット内部に保持し、表示・共有しません。URLにコードを埋め込む `verification_uri_complete` はありません。

利用者はURLを開き、Googleでサインインしてコードを入力します。初めての利用者は、ここでサインアップします。コードは10分で期限切れになります。

### 2. 許可を待つ

取得した `device_code` で次の要求を送ります。`client_id`、`client_secret`、`scope` は不要です。

```sh
curl --request POST 'https://journal.rubydog.jp/api/v1/token' \
  --data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:device_code' \
  --data-urlencode "device_code=$DEVICE_CODE"
```

`$DEVICE_CODE` は手順1で取得した値です。最初の要求も含めて `interval` 秒以上待ち、成功または停止条件まで繰り返します。期限は `expires_in` 秒です。

| HTTP / error                                      | ボットの動作                                           |
| ------------------------------------------------- | ------------------------------------------------------ |
| 200                                               | トークンを保存し、ポーリングを終了する                 |
| 400 / `authorization_pending`                     | 現在の間隔で待って継続する                             |
| 400 / `slow_down`                                 | 以後の待機間隔を5秒増やして継続する                    |
| 400 / `access_denied`                             | 停止する。利用者が拒否した要求を自動で作り直さない     |
| 400 / `expired_token`                             | 停止する。接続が必要なら新しいコードで最初から行う     |
| 400 / `invalid_grant`                             | 停止する。コードが無効または使用済み。新しい接続が必要 |
| 400 / `invalid_request`・`unsupported_grant_type` | 自動再試行せず、リクエストを修正する                   |

認証エラーは `{"error":"authorization_pending","error_description":"..."}` の形式です。判定には `error` を使い、説明文を文字列比較しません。

## データを読み取る {#read}

トークン応答の `access_token` を `$ACCESS_TOKEN` として使います。

```sh
curl 'https://journal.rubydog.jp/api/v1/fiscal-periods' \
  --header "Authorization: Bearer $ACCESS_TOKEN"
```

応答の `fiscalPeriods` から利用者が指定した期間を選び、その `id` を `$FISCAL_PERIOD_ID` に設定します。期間IDを推測したり、先頭の期間を無条件に選んだりしないでください。

```sh
curl "https://journal.rubydog.jp/api/v1/fiscal-periods/$FISCAL_PERIOD_ID/entries" \
  --header "Authorization: Bearer $ACCESS_TOKEN"
```

一覧は対象の全件を返します。現行APIにページ番号・カーソル・件数指定はありません。勘定科目・税区分・事業区分のIDは、それぞれ `/master/book-accounts`・`/master/tax-categories`・`/master/business-categories` で取得します。

## トークンを更新する {#refresh}

アクセストークンは1時間有効です。更新は同じボット内で1つずつ実行し、複数の処理から同じリフレッシュトークンを同時に使わないでください。

```sh
curl --request POST 'https://journal.rubydog.jp/api/v1/token' \
  --data-urlencode 'grant_type=refresh_token' \
  --data-urlencode "refresh_token=$REFRESH_TOKEN"
```

成功したら `access_token` と `refresh_token` を一緒に保存し、古い値を置き換えます。リフレッシュトークンは1回限りで、90日使われないと失効します。使用済みの値を再送すると同じ系列のリフレッシュトークンが無効になります。

更新の応答を通信障害などで受け取れなかった場合、サーバーではすでに処理済みかもしれません。古いトークンを無条件に再送せず、最新の保存値を確認し、回復できなければ接続からやり直します。`invalid_grant` の場合も再認証が必要です。

トークンを会話本文・ログ・ソースコードに載せず、利用するツールの資格情報保存機能などで保持します。許可済みボットの名前変更と取り消しはクラウド版のマイページで行えます。取り消すと、そのボットのアクセスは使えなくなります。

## 書き込みと再試行 {#write}

書き込み前に対象期間の `phase`・`archiveStatus` を確認します。仕訳は借方と貸方の金額を一致させ、日付を期間内に収めます。具体的な入力項目はOpenAPIを参照してください。

- JSONを送るときは `Content-Type: application/json` を付けます。認証の2エンドポイントはフォーム形式も受け付けます。
- 日付は `YYYY-MM-DD`、日時はUTCのISO 8601です。金額は円単位の0以上の整数、事業割合は0〜1です。固定資産の取得価額など、個別の入力にはより厳しい制約があります。
- 名称・摘要・取引先などは400 UTF-16コード単位までです。保存済みの値をそのまま送り直す場合は、この上限にかかりません。
- データAPIの応答では、値がない項目は省略せず `null` を返します。
- `PATCH` は省略した項目を変更しません。`null` を送れる項目とその意味は各スキーマで確認してください。
- 通信が途切れても、書き込みが失敗したとは限りません。結果が不明な作成・更新・削除を無条件に繰り返さず、先に保存状態を読み取ります。
- 仕訳の一括取り込みは `/fiscal-periods/{fiscalPeriodId}/entries/import` を使います。`localId` を付けた同じ仕訳は重複を飛ばすため、部分保存後の再送に利用できます。`virtual:` で始まる `localId` は本締め用に予約されています。
- 汎用の `Idempotency-Key` は提供していません。各操作の重複・再試行条件を確認してください。
- データ変更の応答に付く `X-Request-Id` は問い合わせ用です。変更操作と変更前の内容はサーバーに90日間記録されます。

## エラーから回復する {#errors}

データAPIのエラーには `statusCode`・`code`・`messageForDeveloper`・`messageForUser`・`originalMessage` があります。`code` は `null` の場合もあるため、HTTPステータスを基本に判定します。

| HTTP             | 次の動作                                                                         |
| ---------------- | -------------------------------------------------------------------------------- |
| 400              | 入力値・形式を確認する。同じ要求をそのまま繰り返さない                           |
| 401              | 最新のトークンを確認し、更新または再認証する。ボット取り消しの可能性もある       |
| 403              | 対応していない機能。アーカイブ取り込みはクラウド版では利用不可                 |
| 404              | 指定したID・期間・利用者を確認する                                               |
| 409              | 期間の段階・アーカイブ状態・重複などを確認する                                   |
| 429              | `/device/code` の呼び出しを抑え、`Retry-After` 秒以上待つ                        |
| 503              | メンテナンス中は `code=maintenance_mode_enabled`。間隔を空けて再確認する         |
| 500 / 通信エラー | 読み取りは間隔を空けて再試行。書き込みとトークン交換は処理済みの可能性を確認する |

メンテナンス時の503は、認証エンドポイントでもデータAPIと同じエラー形式になります。通常の認証エラー形式とは分けて扱ってください。

## クラウド版の制約 {#limits}

- 進行中の会計期間は1つです。次の期間を作る前に元の期間をアーカイブします。
- アーカイブした期間は読み取り専用です。APIから次の期間を作っても、元の期間のデータは自動削除されません。削除が必要な場合だけ `purge-archived-data` を使います。
- アーカイブファイルの取り込みは利用できません。無印版で取り込んでください。
- 有効なボットは利用者1人につき20個までです。

## AIアシスタントに渡す {#assistants}

Web上のドキュメント取得とHTTP通信に対応したアシスタントでは、次のように依頼できます。ツール固有の設定方法や、特定製品での動作保証を示すものではありません。

```text
オープン会計の次のガイドとOpenAPIを読んでください。
https://journal.rubydog.jp/api/v1/guide.md
https://journal.rubydog.jp/api/v1/openapi.yaml

まずボットの接続を開始し、私がブラウザで許可するためのURLとコードを教えてください。
接続後、会計期間の一覧を取得し、対象期間を私に確認してください。
今回はデータを読み取るだけにし、作成・編集・削除・締め処理は行わないでください。
トークンは会話に表示しないでください。
```

この依頼文はアシスタントへの操作指示です。APIの権限を読み取り専用に制限するものではありません。
