1. Guides
Synci API
  • Overview
  • Guides
    • Authentication
    • Building OAuth apps
    • Webhooks
    • Pagination, filtering, and sorting
    • Errors
    • Rate limits
    • MCP: Connect AI assistants
  • API Reference
    • Finance
      • Connections
        • List all financial connections
        • Create a new financial connection
        • Get financial connection
        • Delete financial connection
        • Disable financial connection
        • Reconfirm the consent of a financial connection
      • Accounts
        • List all financial accounts
        • Get financial account
        • Update financial account
        • Delete financial account
        • Sync financial account data
        • Reset financial account config to defaults
        • List all account balance entries
        • Get account balance entry
        • List account holdings
        • Get account holding
      • Transactions
        • List all transactions
        • Create a new transaction
        • Get transaction
        • Update transaction
        • Delete transaction
        • Bulk delete transactions
      • Institutions
        • Get supported countries
        • List all supported institutions
        • Get supported institution
    • Destinations
      • YNAB Connections
        • YNAB Budgets
          • YNAB Budget Accounts
            • List all YNAB budget accounts
            • Get YNAB budget account
            • Delete YNAB budget account
          • List all YNAB budgets
          • Get YNAB budget
          • Delete YNAB budget
          • Update YNAB budget
        • List all YNAB connections
        • Create new YNAB connection
        • Get YNAB connection
        • Delete YNAB connection
        • Update YNAB connection
        • Refresh YNAB connection
      • Lunch Money Connections
        • Lunch Money Accounts
          • List all Lunch Money accounts
          • Get Lunch Money account
          • Delete Lunch Money account
        • List all Lunch Money connections
        • Create new Lunch Money connection
        • Get Lunch Money connection
        • Delete Lunch Money connection
        • Update Lunch Money connection
        • Refresh Lunch Money connection
      • Google Sheets Connections
        • Sheets
          • List destination spreadsheets for a connection
          • Register a destination spreadsheet
          • Get a destination spreadsheet
          • Update a destination spreadsheet
          • Delete a destination spreadsheet
          • List the worksheets (tabs) of a spreadsheet
          • Create a new worksheet (tab) in a spreadsheet
        • List all Google Sheets connections
        • Create new Google Sheets connection
        • Get Google Sheets connection
        • Delete Google Sheets connection
        • Update Google Sheets connection
        • Refresh Google Sheets connection
    • Transfer Links
      • List all transfer links
      • Create a new transfer link
      • Get transfer link
      • Update transfer link
      • Delete transfer link
      • Retry transfers for all transfer links
      • Retry transfers for a specific transfer link
    • Transfer Logs
      • List all transfer logs
      • Get transfer log
      • Undo a transfer
      • Undo multiple transfers
    • Rules
      • Create a new rule
      • List all rules
      • Get rule
      • Update rule
      • Delete rule
      • Attach rule to transfer link
      • Detach rule from transfer link
      • Reorder rules for a transfer link
      • Attach rule to a financial account
      • Detach rule from financial account
      • Reorder rules for a financial account
      • Preview a rule against transactions (dry-run)
    • Rule Logs
      • List all rule logs
      • Get rule log
      • Undo multiple rule actions
      • Undo a rule action
    • Webhooks
      • List all webhook events
      • List all webhook endpoints
      • Create new webhook endpoint
      • Get webhook endpoint
      • Update webhook endpoint
      • Delete webhook endpoint
      • Test webhook endpoint
      • Rotate webhook secret
  • ActualBudgetConnections
    • List all Actual Budget connections
      GET
    • Create new Actual Budget connection
      POST
    • Get Actual Budget connection
      GET
    • Update Actual Budget connection
      PUT
    • Delete Actual Budget connection
      DELETE
    • Regenerate setup token
      POST
    • Revoke access credentials
      POST
    • List accounts linked in Actual
      GET
  • Schemas
    • AccountHoldingResource
    • ActualBudgetAccountResource
    • ActualBudgetConnectionResource
    • BalanceTypeEnum
    • BulkDeleteTransactionsRequest
    • BulkUndoRuleLogsRequest
    • BulkUndoTransferLogsRequest
    • CreateFinancialConnectionRequest
    • CreateGoogleSheetTabRequest
    • CreateGoogleSheetsConnectionRequest
    • CreateLunchMoneyConnectionRequest
    • CreateRuleRequest
    • CreateTransactionRequest
    • CreateTransferLinkRequest
    • CreateWebhookEndpointRequest
    • CreateYnabConnectionRequest
    • DestinationTypeEnum
    • EnrichmentProviderEnum
    • FinancialAccount
    • FinancialAccountBalanceResource
    • FinancialAccountResource
    • FinancialConnectionResource
    • GoogleSheetResource
    • GoogleSheetsConnectionResource
    • HealthResource
    • HealthStatusEnum
    • InstitutionConfigMappedDateEnum
    • InstitutionConfigMappedTextEnum
    • InstitutionConfigResource
    • InstitutionResource
    • IntegratorEnum
    • LunchMoneyAccountResource
    • LunchMoneyConnectionResource
    • PreviewRuleRequest
    • ReauthorizeFinancialConnectionRequest
    • RetryTransfersAllLinksRequest
    • RetryTransfersRequest
    • RuleActionResource
    • RuleActionTypeEnum
    • RuleConditionResource
    • RuleLogResource
    • RuleOperatorEnum
    • RuleResource
    • RuleTypeEnum
    • StoreActualBudgetConnectionRequest
    • StoreGoogleSheetRequest
    • SyncFinancialAccountRequest
    • TestWebhookRequest
    • TransactionResource
    • TransactionTypeEnum
    • TransferLink
    • TransferLinkResource
    • TransferLinkSyncModeEnum
    • TransferLogResource
    • TransferLogStatusEnum
    • UpdateActualBudgetConnectionRequest
    • UpdateFinancialAccountRequest
    • UpdateGoogleSheetRequest
    • UpdateGoogleSheetsConnectionRequest
    • UpdateLunchMoneyConnectionRequest
    • UpdateRuleRequest
    • UpdateTransactionRequest
    • UpdateTransferLinkRequest
    • UpdateWebhookEndpointRequest
    • UpdateYnabBudgetRequest
    • UpdateYnabConnectionRequest
    • WebhookEndpointPayloadVersion
    • WebhookEndpointResource
    • WebhookEventResource
    • WebhookEventTypeEnum
    • WebhookTypeEnum
    • YnabBudgetAccountResource
    • YnabBudgetAccountTypeEnum
    • YnabBudgetResource
    • YnabConnectionResource
  1. Guides

Building OAuth apps

OAuth apps let other Synci users grant your application access to their financial data. Unlike a personal access token (which only reaches your own account), an OAuth app uses a consent flow: the user reviews the permissions you request, picks which accounts to share, and can revoke access at any time.
Synci implements OAuth 2.0 authorization code grant with PKCE.

1. Register your app#

In the Synci dashboard, go to Developers → Apps → New app. You will set:
Name: shown to users on the consent screen.
Redirect URIs: up to 5 exact-match https:// URLs where Synci sends users back after they approve. No wildcards, no trailing-slash differences. While your app is in testing, http:// is also allowed for loopback hosts (localhost, 127.0.0.1, ::1) so you can develop locally; loopback URIs must be replaced with https:// before you submit for review.
Permissions (scopes): the scopes your app may request. On any given authorization you can request a subset, never more. See the scope table in Authentication.
Branding: developer or company name, description, homepage, privacy policy, and logo. Required before you can submit for review.

Client credentials#

Every app is a confidential (server-side) client:
Client ID: public identifier, safe to embed in URLs.
Client secret: shown once at creation. Store it securely on your server and never expose it in a browser or mobile app. You can rotate it at any time (the previous secret stops working immediately).
Public or PKCE-only clients (browser-only or mobile apps without a backend) are not currently offered. If you need one, get in touch.

2. The authorization flow#

1
Generate PKCE values and state
Create a random code_verifier (43 to 128 characters), then derive the challenge:
code_challenge = BASE64URL( SHA256( code_verifier ) )
Also generate a random state string to protect against CSRF.
2
Redirect the user to the authorize endpoint
GET https://api.synci.io/oauth/authorize
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https://yourapp.com/callback
  &scope=accounts:read%20transactions:read
  &state=RANDOM_STATE
  &code_challenge=YOUR_CODE_CHALLENGE
  &code_challenge_method=S256
Scopes are space-separated (URL-encoded as %20) and must be a subset of the scopes your app is registered for.
The user signs in, reviews your app's branding and the requested permissions, and, when account-scoped permissions are requested, selects which accounts your app may access. Users approve the request as a whole; they cannot deny individual scopes.
On approval, Synci redirects back to your redirect URI:
https://yourapp.com/callback?code=AUTH_CODE&state=RANDOM_STATE
Verify that state matches what you sent before continuing. The code is single-use and expires after about 10 minutes.
On denial, the redirect carries ?error=access_denied instead of a code.
3
Exchange the code for tokens
From your backend, POST to the token endpoint. The body must be application/x-www-form-urlencoded, not JSON:
Response:
{
  "token_type": "Bearer",
  "expires_in": 3600,
  "access_token": "eyJ0eXAiOi...",
  "refresh_token": "def50200..."
}
Access tokens are valid for 1 hour. Refresh tokens are valid for 30 days and rotate on every use.
4
Call the API
The token can reach exactly what the user approved: requests outside the granted scopes return 403, and accounts the user did not select return 404.
5
Refresh tokens
When the access token expires, exchange the refresh token (again form-urlencoded):
Each refresh returns a new access token and a new refresh token. Always store the newly returned refresh token; the one you just used is invalidated.

3. App review lifecycle#

StateWho can authorizeEditing
TestingYou and invited testersChanges take effect immediately
Pending reviewNo new authorizationsLocked while under review
ApprovedAny Synci user; your app is marked verifiedChanges to branding, scopes, and redirect URIs are queued for re-review before taking effect
RejectedNo oneEdit and resubmit; a reason is provided
You can return an approved app to development at any time; this unpublishes it without revoking existing user connections. Deleting an app or rotating its secret requires password confirmation in the dashboard.

4. Good to know#

The token endpoint is form-urlencoded, per the OAuth spec. Sending JSON fails with invalid_client.
Redirect URIs match exactly: no wildcards, and https://yourapp.com/callback is not the same as https://yourapp.com/callback/.
Users can revoke your app at any time from their Synci settings. All of its tokens stop working immediately and the user must authorize again.
Suspended apps are cut off immediately: existing tokens are rejected and refresh is blocked.
Request minimal scopes. Users are more likely to approve an app that asks only for what it needs, and reviews go faster.

5. Common errors#

ErrorCause
invalid_clientWrong or missing client_id or client_secret, or the token request was sent as JSON instead of form-urlencoded.
invalid_grantThe authorization code expired or was already used, the code_verifier does not match the original code_challenge, or the refresh token was already rotated or revoked.
invalid_scopeA requested scope is not among the scopes your app is registered for.
access_denied (on the redirect)The user declined the authorization request.
403 on an API callThe token lacks the required scope for that endpoint.
404 on an accountThe user did not grant your app that account.
Modified at 2026-07-11 12:30:30
Previous
Authentication
Next
Webhooks
Built with