{% extends "base.html" %} {% block title %}Schwab Connection{% endblock %} {% block page_title %}Schwab Bank Sync{% endblock %} {% block topbar_actions %} {% if connection %}
{% endif %} {% endblock %} {% block content %} {% if not schwab_configured %}
Schwab credentials not configured

Register your app at developer.schwab.com, then add these to your .env:

SCHWAB_CLIENT_ID=your-client-id
SCHWAB_CLIENT_SECRET=your-client-secret
SCHWAB_REDIRECT_URI=https://pfm.ngodanguyen.tech/schwab/callback

Also register https://pfm.ngodanguyen.tech/schwab/callback as the redirect URI in the Schwab developer portal, then restart the app.

{% endif %} {% if connection %}
Charles Schwab
Connected {{ connection.created_at.strftime('%b %d, %Y') }} · Last synced: {{ connection.last_synced_at.strftime('%b %d, %H:%M') if connection.last_synced_at else 'Never' }} {% if connection.token_is_expired %} · Token expired — sync will auto-refresh {% endif %}
Manage Mapping
{% if accounts %}
Accounts
{% for sa in accounts %}
{{ sa.account_name }} {% if sa.last_sync_date %} synced {{ sa.last_sync_date.strftime('%b %d') }} {% endif %}
{{ sa.account_number_display }} · {{ sa.account_type }} {% if sa.pfm_account %} · → {{ sa.pfm_account.name }} {% else %} · Not mapped {% endif %}
{% if sa.pfm_account %} Sync
{% else %} Map Account {% endif %}
{% endfor %}
{% else %}
No accounts mapped

Link each Schwab account to a PFM account to start syncing.

Map Accounts
{% endif %} {% else %}
Connect Charles Schwab

Sync checking, savings, and brokerage transactions directly from Schwab.

{% if schwab_configured %} Connect Schwab Account {% else %}

Configure credentials first (see above)

{% endif %}
{% endif %} {% endblock %}