MoneyForward Cloud Integration

MoneyForward Cloud Integration #

MoneyForward Cloud is a suite of Japanese cloud accounting products. BonsAI integrates with Cloud Accounting (クラウド会計) and Cloud Invoice (クラウド請求書) for master data synchronization and AR invoice reads.

Architecture Overview #

MoneyForward is not a single-app integration like Xero or QBO. Each MF Cloud product is a separate service, but Cloud Accounting and Cloud Invoice share a unified OAuth auth server at https://api.biz.moneyforward.com. This lets a single OAuth app request scopes from both products in one authorization flow.

User → BonsAI OAuth authorize → MF App Portal consent
                                    ↓
                               auth code callback
                                    ↓
                        BonsAI exchanges for tokens
                                    ↓
              ┌─────────────────────────────────────────────┐
              │   Cloud Accounting API (master data)        │
              │   https://api-accounting.moneyforward.com   │
              ├─────────────────────────────────────────────┤
              │   Cloud Invoice API (AR invoices)           │
              │   https://invoice.moneyforward.com          │
              └─────────────────────────────────────────────┘

Products & Scopes #

Cloud Accounting (クラウド会計) #

Provides COA master data: accounts, taxes, departments, trade partners, journal entries.

Scope Access
mfc/accounting/offices.read Office/company info
mfc/accounting/accounts.read Chart of accounts
mfc/accounting/departments.read Departments
mfc/accounting/taxes.read Tax rates/codes
mfc/accounting/trade_partners.read Trade partners (contacts)
mfc/accounting/trade_partners.write Create/update trade partners
mfc/accounting/journal.read Journal entries

Cloud Invoice (クラウド請求書) #

Provides AR invoice data: billings, partners, items, quotes.

Scope Access
mfc/invoice/data.read All Invoice API objects (read-only)

Multiple scopes are space-delimited in the authorize URL:

scope=mfc/accounting/offices.read mfc/accounting/accounts.read mfc/invoice/data.read

Auth Endpoints #

All endpoints below are for the unified auth server shared by Cloud Accounting and Cloud Invoice.

Endpoint URL
Authorization https://api.biz.moneyforward.com/authorize
Token https://api.biz.moneyforward.com/token
Revoke https://api.biz.moneyforward.com/revoke

Client authentication method: CLIENT_SECRET_BASIC (HTTP Basic Auth with client_id:client_secret in the Authorization header).

Token Lifetimes #

Token Lifetime Notes
Access token 1 hour (3600s)
Refresh token 18 months (~540 days / 46,656,000s) Expiry resets on each use
Auth code 10 minutes

Refresh token rotation: Each refresh issues a new access + refresh token pair. The old tokens are invalidated immediately. The token store must persist both the new access_token and the new refresh_token from every refresh response.

API Base URLs #

Product API Base
Cloud Accounting https://api-accounting.moneyforward.com/api/v3/
Cloud Invoice https://invoice.moneyforward.com/api/v3/

OAuth App Registration #

App Portal URL #

https://biz.moneyforward.com/app_portal

Navigate from the MF Cloud management console → sidebar → App Portal.

Pre-requisites #

Before registering an OAuth app, the MoneyForward Cloud account must have:

  1. An active MF Cloud subscription with Cloud Accounting and/or Cloud Invoice enabled (any plan tier).
  2. A user with 全権管理者 (superadmin) permission to activate the App Portal for the first time.
  3. A user with アプリ開発 (App Development) permission to register the app and obtain credentials.
  4. For production: a separate user with アプリ連携 (App Integration) permission to authorize the OAuth consent screen (MF best practice: keep dev and auth roles separate in production).

Registration Steps #

  1. Log into MoneyForward Cloud management console.

  2. Open App Portal from the left sidebar.

  3. Click 「アプリを作成」 (Create App).

  4. Fill in the registration form:

    Field Value
    App name BonsAI (Cloud Accounting + Invoice) [env]
    Redirect URI https://[bonsapi-host]/api/v1/integrations/oauth/authorize/callback
    Client auth method CLIENT_SECRET_BASIC
    Scopes Select all required scopes listed above
  5. After creation, copy the Client ID and Client Secret.

  6. Store credentials in Doppler (see Credential Storage).

Per-Environment Configuration #

Register one app per environment:

Environment App Name Suffix Redirect URI Host
dev_local [dev] http://localhost:8080
dev_aws [dev] Dev environment bonsapi host
prod [prod] Production bonsapi host

Full callback URL pattern:

{bonsapi-host}/api/v1/integrations/oauth/authorize/callback

Credential Storage #

Doppler Keys #

All MoneyForward credentials are stored in Doppler under project bonsai:

Doppler Key Description
MONEY_FORWARD_CLIENT_ID OAuth Client ID
MONEY_FORWARD_CLIENT_SECRET OAuth Client Secret

These are set per Doppler config (dev_local, dev_aws, prod).

Local Development #

For local development, credentials can be configured in .config.yaml:

moneyforward:
  client_id: ""
  client_secret: ""

These are mapped to environment variables by override-coder-env.sh.

Credential Rotation #

  1. Create new credentials in the MF App Portal:

    • Open App Portal → select the app → regenerate client secret.
    • The old secret remains valid until you explicitly revoke it (if MF supports dual secrets), or is immediately invalidated (check portal behavior).
  2. Update Doppler:

    doppler secrets set MONEY_FORWARD_CLIENT_SECRET="new-secret" \
      --project bonsai --config <env>
    
  3. Restart services to pick up new secrets:

    kubectl rollout restart deployment/bonsapi-deployment
    
  4. Verify the integration still works by triggering a token refresh.

  5. Document the rotation in the change log.

Revoking a Connection #

To revoke a user’s OAuth connection:

  1. Via API — POST to the revoke endpoint:

    POST https://api.biz.moneyforward.com/revoke
    Content-Type: application/x-www-form-urlencoded
    Authorization: Basic base64(client_id:client_secret)
    
    token={refresh_token}
    
  2. Via MF Portal — The connected user can disconnect the app from their MF Cloud settings → 連携アプリ管理 (Connected App Management).

  3. Verify revocation — After revoking, confirm a 401 Unauthorized response when using the old access token:

    curl -H "Authorization: Bearer {old_access_token}" \
      https://api-accounting.moneyforward.com/api/v3/offices
    # Expected: 401 Unauthorized
    

Important Constraints #

No Sandbox Environment #

MoneyForward Cloud does not provide a sandbox or test environment. All dev/staging testing requires a real paid MF Cloud account. This is a known limitation and must be budgeted for during development.

  • Each environment (dev, staging, prod) needs its own OAuth app registration.
  • Test data created during development exists in the real MF Cloud account.
  • Use a dedicated development MF Cloud account to avoid polluting customer data.

Region #

MoneyForward Cloud operates Japan only. There is a single global API endpoint with no regional split.

Rate Limits #

Refer to the MoneyForward API documentation for current rate limit policies. The Cloud Accounting API applies per-endpoint rate limits.

Future Products (Post-MVP) #

The following MF Cloud products use separate legacy OAuth servers and will require independent OAuth app registrations if integrated:

Product Auth Server Status
Cloud Expense (クラウド経費) https://expense.moneyforward.com/oauth/ Post-MVP
Cloud Accounts Payable (クラウド債務支払) https://payable.moneyforward.com/oauth/ Post-MVP

Troubleshooting #

“Invalid Redirect URI” during OAuth #

  • Verify the redirect URI in the MF App Portal matches exactly (including protocol and trailing slashes).
  • Check that the bonsapi host in the environment matches the registered redirect URI.

Token Refresh Fails #

  • Refresh tokens are single-use. If a refresh was attempted but the response was not persisted (e.g., crash mid-refresh), the old refresh token is already invalidated.
  • The user must re-authorize through the OAuth flow.
  • Check that both access_token and refresh_token are saved after every refresh.

403 on API Calls #

  • Verify the requested scope was included in the OAuth authorization.
  • Check that the MF Cloud account has the required product subscription active.

See Also #