🧪 C-Town — Developer Space
🎓 Getting Started: HTTP Basic Authentication
- Get Your Developer ID. AppFolio → your account name → Admin → Developer ID (Developer Details card). In this account the Developer ID is also your Client ID.
- Get Your Basic Auth Credentials. Beneath API Credentials, select Basic Auth, then Generate a Client Secret on that row. Store it somewhere safe — it's shown only once.
- Create Your Encoded String. In Mac Terminal run
echo -n "{ClientID}:{ClientSecret}" | base64and copy the result.
Replace in the request command:
{YOUR-DEVELOPER-ID}— your Developer ID (step 1){YOUR-ENCODED-STRING}— the Base64 value (step 3){resource}— the desired resource (for example,properties,tenants, orcharges)
Note: You'll need separate credentials for each customer database when using Basic Auth.
🔑 Database API Credentials (v0)
Two pairs, two jobs: the Client ID + Secret build the Encoded String; then the Developer ID + Encoded String are what every request sends (
X-AppFolio-Developer-ID header + Authorization: Basic). Developer ID and Client ID are different values.
AppFolio → account name → Admin → Developer ID card. Sent as
X-AppFolio-Developer-ID.Basic Auth — builds the Encoded String
From AppFolio → API Credentials → Basic Auth row (Client ID) + Generate a Client Secret.
=
base64(ClientID:ClientSecret). Generate it with ⚙️ above, or in Terminal: echo -n "ClientID:ClientSecret" | base64 | tr -d '\n'
— Not tested
Test against
📄 API Docs ↗
Stored in Supabase (
app_settings → key appfolio_dev_ctown). Used by Post Reports to create records in AppFolio (bills, vendors, etc.) via the appfolio-proxy Edge Function.
📡 How to Make an API Request
curl -g --request GET 'https://api.appfolio.com/api/v0/{resource}/' \
--header 'X-AppFolio-Developer-ID: {YOUR-DEVELOPER-ID}' \
--header 'Authorization: Basic {YOUR-ENCODED-STRING}'
A
200 means your credentials work. 401 = bad credentials. 403/404 = auth is fine but that resource is restricted (still proves the connection).🧪 Nexus — Developer Space
🎓 Nexus is a SEPARATE AppFolio account (
nexusplus)These v0 Database-API credentials are different from C-Town's — generate a fresh set inside the nexusplus account:
- Developer ID. nexusplus.appfolio.com → account name → Admin → Developer ID card.
- Basic Auth Client Secret. Under API Credentials → Basic Auth row → Generate a Client Secret (shown once — save it).
- Encoded String. ⚙️ Generate below, or Terminal:
echo -n "{ClientID}:{ClientSecret}" | base64
🔑 Database API Credentials (v0) — Nexus
Two pairs, two jobs: the Client ID + Secret build the Encoded String; then the Developer ID + Encoded String are what every request sends (
X-AppFolio-Developer-ID header + Authorization: Basic).
AppFolio (nexusplus) → account name → Admin → Developer ID card. Sent as
X-AppFolio-Developer-ID.Basic Auth — builds the Encoded String
From nexusplus → API Credentials → Basic Auth row (Client ID) + Generate a Client Secret.
=
base64(ClientID:ClientSecret). Generate it with ⚙️ above, or in Terminal: echo -n "ClientID:ClientSecret" | base64 | tr -d '\n'
— Not tested
Test against
📄 API Docs ↗
Stored in Supabase (
app_settings → key appfolio_dev_nexus). Used by Post Reports → Construction Bills (portfolio = Nexus) to create records in the nexusplus AppFolio account.
🪝 Webhooks
Receive real-time event notifications from AppFolio (create / update / destroy)
📥 Your Webhook URL
The
appfolio-webhook Edge Function. Must be deployed with Verify JWT off (--no-verify-jwt) so AppFolio can reach it.
Every delivery is signed (
X-JWS-Signature) and verified against AppFolio's public keys before it's trusted. Unverified events are still logged but flagged and never acted on. During setup, leave WEBHOOK_REQUIRE_VALID unset so you can confirm delivery, then set it to true.
⚙️ Setup steps
- Run
appfolio-webhooks-migration.sqlin Supabase. - Deploy the function:
supabase functions deploy appfolio-webhook --no-verify-jwt - In AppFolio → Admin → Webhooks, add the URL above and name it.
- Under Topic Subscriptions, check the topics you want (below), then Send Test Event.
- The test (and all future events) appear in the log at the bottom of this page.
🏢 C-Town — API Credentials
🔑 Credentials
— Not tested
Credentials are stored securely in Supabase (
app_settings). They are used by Manage Listings, Budget Dashboard, Classic Collections, and Client Orbit.
🏗️ Nexus — API Credentials
🔑 Credentials
— Not tested
Credentials are stored securely in Supabase (
app_settings). They are used by Manage Listings, Budget Dashboard, Classic Collections, and Client Orbit.
🛡️ Tenant Screening — TransUnion SmartMove
One WilCodex-wide connection. Used by the secured application (
apply.html) across every brand — Classic, Premier & Nexus.🔑 SmartMove Connection
— Not tested
Stored securely in Supabase (
app_settings → key smartmove, admin/manager only) and read by the applicant-screening-submit Edge Function. The applicant enters their SSN on TransUnion's own site — it is never collected or stored here.
⚙️ Get Settings
Configure which AppFolio reports each tool can access
📊 Sync Status
Last synced data for each report — readable by all tools
Synced data is stored in
appfolio_report_data. Other tools (Classic Collections, Client Orbit, Budget Dashboard) read from this table — syncing here keeps all tools up to date without each tool hitting the AppFolio API directly.
🧮 Data QA — Manual vs Sync
Upload a CSV you exported from AppFolio, then compare its totals against what the live sync pulled. Catches silent data drift.
⬆️ Upload a CSV report
The manual side is whatever CSV you upload here (stored in
appfolio_manual_uploads). The synced side is the live pull in appfolio_report_data. A row is ✓ Match when the two totals are within $1.00 or 0.1%; otherwise ✕ Mismatch. Both sides sum the same column — re-upload after each sync to re-check.
🔎 Reconciliation — Sync Health
Proves every AppFolio report and reference table actually landed in WilCodex — fresh, complete, and internally consistent. Read-only.
Running checks…
How to read this. Green = healthy. Amber = worth a look (stale, or a count gap that may be legitimate). Red = the sync broke or dropped data — check Sync Status for the failing report, then re-run it. Freshness SLA: report tables are expected within ~12h (cron runs 6a/1p/6p ET); reference tables within ~30h.
🧾 Post Settings
Configure POST / create actions sent to the AppFolio Database API (
v0) — e.g. creating bills
These actions use the Developer Space credentials (Developer ID + Basic Auth), not the Reports credentials. Set those up first under Developer Space → C-Town.
📮 Post Log
History of records submitted to AppFolio via the Database API (v0)
Each submission is logged to
appfolio_post_log with the request, the HTTP status, and AppFolio's response (including the new record's id on success).
🏗️ Construction → AppFolio
Stage construction materials + labor as AppFolio Bills / Journal Entries — review, then post
PREPARE mode. Nothing posts automatically. Building only stages payloads for review. The model:
1 vendor = 1 invoice = 1 transaction, many lines each allocated to Property / Unit / GL. Material lines → GL 6100, labor lines → GL 6110. Company-card / already-paid → Journal Entry; net-terms invoice → open AP Bill. Uses Developer Space creds.