Adom Desktop - Fusion 360 Bridge
Public Made by Adomby adom
Drive Autodesk Fusion 360 from the cloud via Adom Desktop: component libraries, IPC package generation, board layout, exports (STEP/Gerbers/BOM/CPL), fast APS cloud search, and parametric modeling.
name: fusion-aps-signin description: Drive the Autodesk sign-in flow in the user's real browser to set up APS (Autodesk Platform Services) for the Fusion bridge's fusion_aps_* cloud search — open a dedicated browser window, foreground it, MONITOR the sign-in, and auto-retrieve + enter the emailed one-time passcode (OTP) via adom-google before it expires. Use when signing into Autodesk/APS, registering an APS app, configuring fusion_aps_search, or any "log me into Fusion/Autodesk for APS" request. Trigger words — aps signin, sign in to autodesk, autodesk otp, fusion aps login, register aps app, aps client id, fusion_aps_signin, autodesk verification code, link google account autodesk.
Fusion / APS sign-in (driven, with auto-OTP)
Goal: get the user signed into aps.autodesk.com in their real browser so you can
register an APS app and configure the Fusion bridge's fusion_aps_* search. The hard
part is Autodesk's email OTP, which expires fast — the user may walk away ("get a
cup of coffee"), so you must monitor the flow and turn the code around in seconds.
All browser steps use the native-browser extension verbs (nbrowser_*) against the
AD-connected laptop: adom-desktop --target <laptop> nbrowser_* '{...}'.
Working principles (non-negotiable)
- DO IT YOURSELF. NEVER ask the user to do anything manually that you can do. That is the entire point of the Adom AI ecosystem — the AI drives, the user doesn't. Don't hand the user a "go create the app and paste me the Client ID" cop-out; drive the whole flow (open windows, fill forms, fetch the OTP, click through) to completion yourself. Only surface a real decision (a genuine fork) — never offload mechanical work.
- NEVER navigate the user's CURRENT page/window away from them — that hijacks their live
work (e.g. their Edge tab) and is unacceptable. ALWAYS open a NEW window
(
nbrowser_open_window {url}) for whatever you need and drive ONLY that window'ssessionId. Opening your own windows and driving them is expected; reusing/navigating a window the user is viewing is not.desktop_bring_to_frontto surface a window for the user is fine.
Golden rules (learned the hard way)
- OTP expires in ~a few minutes. Be FAST. Don't go fetch-and-think between resend and entry — fetch the code and enter it in the same burst. We burned the 1st code dithering; 3rd round worked by resending and entering immediately.
- MONITOR the sign-in, don't fire-and-forget. Poll the page state every few seconds (the user may step away). Detect each transition: email → OTP → "code expired" → "account already exists" → "linked" → portal. Never assume; re-read the page.
- Open a DEDICATED browser window with
nbrowser_open_windowand target it bysessionIdin everynbrowser_eval/type/click. The extension refuses to drive PWA / installed-app windows (e.g. "Hydrogen - Chat") andnbrowser_evaldefaults to the foreground tab — which is often the wrong (PWA) window. - Foreground it with
desktop_bring_to_front(the AD verb) so the user can see/act on the login.nbrowser_focus_windowis NOT implemented. - Proactively use adom-google. Autodesk emails the OTP — you can read it via the
adom-googleGmail API passthrough. If adom-google isn't set up, TELL the user it exists and offer to set it up (adom-google auth) so you can fetch the code for them. Gmail for Adom = [email protected] (work account).
Step-by-step
1. Open + foreground a dedicated window at the APS portal
adom-desktop --target <laptop> nbrowser_open_window '{"url":"https://aps.autodesk.com/myapps/"}'
# capture sessionId (e.g. s29) from the result; use it in EVERY later call
adom-desktop --target <laptop> desktop_bring_to_front '{...the browser window...}' # so the user sees it
Read state (always pass the sessionId):
nbrowser_eval '{"sessionId":"s29","expression":"JSON.stringify({url:location.href,title:document.title,body:document.body.innerText.slice(0,300)})"}'
If location.href is signin.autodesk.com, the profile has no active Autodesk session —
the user must start sign-in (enter email, or an SSO button). You won't type their password.
2. Monitor for the OTP screen
Poll nbrowser_eval every ~3-5s. The OTP page title is "Linkable email OTP - Autodesk"
with six single-char boxes input[name=pin-1..pin-6] and body "Enter the code from your
email. … Email sent."
3. Fetch the freshest OTP from Gmail (adom-google)
Check auth first: adom-google status (need a refresh token + gmail scope). Then:
# list newest Autodesk passcode mail (strip the leading "HTTP 200 ..." line)
MID=$(adom-google api "https://gmail.googleapis.com/gmail/v1/users/me/messages" \
-q "q=from:autodesk subject:passcode newer_than:1h" -q "maxResults=1" \
| tail -n +2 | python3 -c "import sys,json;print(json.load(sys.stdin)['messages'][0]['id'])")
# get it, pull the 6-digit code from the snippet ("Code: 205753")
adom-google api "https://gmail.googleapis.com/gmail/v1/users/me/messages/$MID" -q "format=full" \
| tail -n +2 | python3 -c "import sys,json,re;d=json.load(sys.stdin);print(re.search(r'Code:\s*(\d{6})',d['snippet']).group(1))"
Always take the newest message (the email footer also contains 000000/212121 noise —
match Code:\s*(\d{6}), not any 6 digits).
4. Enter the code — digit-by-digit (boxes are maxlen-1, NO auto-advance)
Bulk-typing the whole string only fills box 1. Focus each box, type its digit:
for i in 1 2 3 4 5 6; do
D=$(echo "$CODE" | cut -c$i)
nbrowser_eval '{"sessionId":"s29","expression":"document.querySelector('input[name=pin-'$i']').focus()"}'
nbrowser_type '{"sessionId":"s29","text":"'$D'"}'
done
nbrowser_click '{"sessionId":"s29","text":"Next"}'
Verify before submitting: read [...].map(i=>i.value).join("") == the code.
5. If "This code has expired" → resend + redo FAST
nbrowser_click '{"sessionId":"s29","text":"Resend"}'
# wait ~12s, fetch the NEWEST code (step 3), enter immediately (step 4)
6. "Account already exists" (Google-federated account)
Body: "An Autodesk account already exists with the email … sign in with Google … link …". Click "Link Google account". If the Google session is already active in Chrome it links instantly ("Google account linked … Continue in 5 seconds") and lands in the portal — no account picker. If a Google picker appears, pick [email protected].
7. First-time APS → accept Terms of Service
First portal visit shows "Welcome aboard! … accept our Terms of Service". Accept it.
7.5 Developer-profile form (REQUIRED before you can create an app — you must fill it)
First-time APS gates app creation behind a one-time developer/company profile at
https://aps.autodesk.com/myapps/create ("Ready for next steps?"). YOU fill it from the
user's profile memory (user_profile.md — company, website, address). Fields seen:
company, website, country, stateProvince, city, postalCode (plain text) and
roleId, accountPurpose (MUI comboboxes) + a tosAgreed checkbox.
- Plain text: set via the native value setter + dispatch
input+change+blur(MUI only enables Submit after these fire):nbrowser_eval set vals {company:"Adom Industries, Inc.",website:"https://adom.inc", city:"Fort Worth",stateProvince:"TX",postalCode:"76177"} // country prefills "US" - Comboboxes — can't just set
.value; click to open, then click the option by text (click-by-text finds it even when not in the visible top-N; typing to filter often does NOT work). The fields and good picks for Adom:roleId= Business owner/Entrepreneur (John is the founder)accountPurpose= Business- Industry (select up to 3) — REQUIRED, and it's the one that silently blocks Submit.
It has NO
nameattr (MUI multiselect) — find it by its label "Industry (select up to 3)" (map each input to its nearest ancestor's label text + getBoundingClientRect, then click the field's center coords). Pick Industrial machinery (Adom = PCB/electronics mfg).
- Tick
tosAgreed(click the "I agree to the Autodesk Platform Services" label). It re-resets to false after combobox interactions / re-renders — re-verify it's checked right before Submit. - Submit silently no-ops while ANY required field is invalid, with the button still
enabledand NO scrape-able error. When Submit won't advance, take a screenshot (nbrowser_screenshot {sessionId}) and READ it — inline "Please fill out this field" tooltips (e.g. the empty Industry box) only show visually, not in the DOM you're scraping. This is the fastest way to find a missed required field. - Field coords from
getBoundingClientRectare in PAGE space (whatnbrowser_click {x,y}wants) — do NOT use screenshot pixel coords (the shot is downscaled, different origin). Known profile values (Adom / John): Company "Adom Industries, Inc.", Website https://adom.inc, 4400 Alliance Gateway Fwy, Fort Worth, TX 76177, US, [email protected].
7.55 Get the FREE APS plan (drive the whole checkout yourself — incl. the card)
Newer APS gates app creation behind a developer hub, which requires an APS plan. The Free tier is $0 but Autodesk requires a payment method "to verify identity" (no charge). The AI drives 100% of this, including entering the card. Live-verified flow:
- New window →
https://aps.autodesk.com/hubs/→ the "It seems you don't have a hub yet" page → Step 1 "Get an APS plan" → click "View options" (or go straight tohttps://www.autodesk.com/products/autodesk-platform-services/overview). - On the pricing tiers (3 columns: Free | Prepay $99 | Pay-as-you-go), click the
leftmost "Add to Cart" = the Free tier. (Get all
Add to Cartrects, sort by x, take the smallest — Free is the left column. NEVER click the paid columns.) - Cart drawer shows "APS Free — $0.00", SUBTOTAL $0.00. Click Check out.
checkout.autodesk.com— a 3-step accordion: Cart → Customer details → Payment, with Order summary TOTAL $0.00. Click Continue; an abandon-cart modal ("Don't leave your cart behind!") may pop — click CONTINUE CHECKOUT, then Continue again. Customer details auto-fill from the Autodesk account. It lands open on Payment.- ⚠️ VERIFY TOTAL = $0.00 before doing anything in Payment. If it's ever nonzero, STOP — never proceed (hard rule: no user is ever charged).
- Payment — almost always a card is ALREADY on file (no card entry needed). Almost every Adom user has a PAID Fusion 360 subscription, which means Autodesk already has their payment method on file. So the Payment step will typically show an existing card — SELECT it and move on. The AI completes this with zero card handling and zero user input. Only in the rare case of NO card on file do you fall back to collecting one from the user (their own card, ID-verification only; TREAT AS SENSITIVE — never echo/store/log it). Either way, then click Submit order (agrees to Autodesk's $0 Online Purchase Terms; auto-renews at $0).
- After the $0 order confirms, continue to the hub.
7.6 Create the developer hub (manage.autodesk.com)
Per Autodesk docs: manage.autodesk.com → Products and Services → Hubs → Create hub →
select APS developer hub → enter a name (e.g. "Adom") + optional description → Create
and Activate. (The account may already show an org hub named "Adom" at
manage.autodesk.com/hubs-list; if a usable APS developer hub already exists, use it.)
If routes 404 / loop, open a FRESH window and retry — don't blind-click, and don't offload it.
7.7 (was 7.6) Register the app — drive it, don't hand it off
After the profile, newer APS routes app creation through a developer hub:
/myapps/create → /hubs/@personal/applications/create may 404 ("Not found"), and /myapps
redirects to "you don't have a hub yet" with a Create hub button that bounces to
manage.autodesk.com/hubs-list (a DIFFERENT portal; the account may already list an org hub
like "Adom"). This area is non-linear and account-structural. If it 404s / loops, don't blind-click —
open a FRESH window, reload, and work the hub→app path yourself (create/select the hub, then
the app). Drive it to a Client ID yourself; do NOT offload it to the user. Once you have the
Client ID, fusion_aps_set_client_id → fusion_aps_signin → fusion_aps_search.
8. Register the APS app (then configure the bridge)
Create App → enable Data Management API → Callback URL =
http://localhost:8917/fusion-aps/callback (must match the bridge's REDIRECT_URI
EXACTLY) → create → copy the Client ID (PKCE = public client; the secret is unused).
Then:
adom-desktop --target <laptop> fusion_aps_set_client_id '{"clientId":"<CLIENT_ID>"}'
adom-desktop --target <laptop> fusion_aps_signin '{}' # opens browser; bg listener on :8917 stores the token
# poll fusion_aps_status until {"data":{"signedIn":true,"tokenLive":true}}
adom-desktop --target <laptop> fusion_aps_search '{"query":"<part name>"}'
LIVE-VERIFIED end-to-end run (2026-06-26, Adom org) — the exact sequence
This whole flow was driven live and works. Replicate it per org:
- Sign in (§1–7): new window → aps.autodesk.com → email → OTP from Gmail (adom-google) → "Account already exists" → Link Google account → lands in APS.
- Dev profile (§7.5): fill from user profile; Industry is REQUIRED (screenshot to catch it); role=Business owner, purpose=Business, Industry=Industrial machinery; Submit.
- Free plan (§7.55): aps.autodesk.com/hubs → "Get an APS plan" → View options → pricing: leftmost "Add to Cart" = Free → cart shows "APS Free $0.00" → Check out → checkout.autodesk.com 3-step accordion (Cart→Customer details→Payment), TOTAL $0.00 → Continue (+ "CONTINUE CHECKOUT" on the abandon-cart modal) → Payment step almost always already shows an existing card on file (Fusion subscribers) ✅ → Submit order → "Order Confirmation". $0, existing card, no card entry.
- APS Developer Hub (§7.6): manage.autodesk.com → Products and services → Hubs → Create hub ▾ → APS Developer Hub → name "Adom APS" → Create & Activate (takes a minute). NOTE: this is a CREDENTIAL container with ZERO files — NOT the team's data hub.
- Register the app (§7.7): aps.autodesk.com/myapps → hub now selectable → Create
application → Name "Adom Fusion Bridge" → app-type = "Desktop, Mobile, Single-Page App"
(radio value
native= Authorization Code with PKCE) → Create. ⭐ PKCE app type = "Paid APIs are unavailable" → structurally can't be charged (1st never-charge lock). - Callbacks + APIs: in App settings → Callback URL section, the default is
http://localhost:8080/. Click "+ Add URL" 5× (→ 6 fields), fill all 6 with the bridge's registered set (all_registered_callbacks()): localhost+127.0.0.1 × ports 8917/8918/8920. API Access defaults to all free APIs incl. Data Management (keep). Click Save changes (find it by coords — click-by-text can hit the wrong element). - Client ID: App settings → Client Credentials → copy the Client ID (public PKCE id; NO secret). Extract from the DOM, not a pixel read.
- Wire + sign in:
fusion_aps_set_client_id {clientId}→fusion_aps_signin(bridge opens consent, listens on the bound port) → pollfusion_aps_statusuntilsignedIn:true→fusion_aps_search {query}→ prove it returns files from the team's shared Main folder.
Never-charge — TRIPLE locked (don't weaken any of these)
- The PKCE app type cannot use paid APIs (Autodesk-enforced).
- The bridge's free-endpoint allowlist (
/project/v1/,/data/v1/only). - The bridge's monthly hard cap (fails closed). Card on file = identity verification only.
Port choice for the callback
Check availability LIVE on the box (no AD verb exists): python bind-test on 127.0.0.1 +
netsh int ipv4 show excludedportrange protocol=tcp. 8917/8918/8920 verified free + outside
Windows reserved ranges (5357, 27339, 50000-50059). The box runs ~67 listeners — don't assume.
Gotchas
nbrowser_eval/type/clickwithoutsessionIdhit the foreground tab → often the wrong (PWA) window. Always pass the dedicatedsessionId.adom-google apiprints aHTTP 200 GET …header line before the JSON —tail -n +2.- The bridge relay only forwards
output/data/success/error/_hint— irrelevant here but relevant when readingfusion_aps_*results (fields live underdata). - Don't auto-enter the user's Autodesk password or drive their Google consent — identity decisions are theirs; automate the OTP + form-filling, not the credentials.
⭐ APS AUTH-001 self-heal — the app lost its Data Management API product (verified live 2026-07-14)
Symptom: fusion_aps_signin now returns errorCode: "aps_app_missing_product" (the bridge probes
the /authorize endpoint server-side and detects it BEFORE opening a browser), or you see the raw
{"errorCode":"AUTH-001","developerMessage":"The client_id specified does not have access to the api product"} on the authorize page. It means the org's APS app at aps.autodesk.com/myapps lost its Data
Management API product entitlement (it can work for months, then break). The app config often still
looks correct — the fix is a forced re-commit.
Recovery (drive with ABE/nbrowser — install the extension FIRST if it isn't; coordinate-clicking the portal is fragile and Edge crashes):
nbrowser_open_window {sessionId, thread, purpose, profile:<warm Edge/Chrome>, url:"https://aps.autodesk.com/myapps/"}→ open the app whose Client ID matches (in the org's "Adom APS" dev hub).- App-settings → API Access: confirm Data Management API is checked. Then force a re-commit —
nbrowser_evala click on the visible Save button:(()=>{var b=[...document.querySelectorAll("button")].filter(x=>/save changes/i.test(x.textContent)&&x.offsetParent!==null);if(b.length)b[0].click();return JSON.stringify({n:b.length})})()(the bare text "Save changes" matches ~9 hidden duplicates, sonbrowser_click {text}is ambiguous — use the offsetParent filter). If Save is disabled, open the API dropdown and toggle one unneeded API off first to dirty the form. - Wait 1–3 min for Autodesk to propagate the entitlement.
- Retry
fusion_aps_signin→ it now reaches the consent screen ("… is requesting permission … View/Manage/Write your data … Allow").nbrowser_navigatethe session to the freshauthUrl, thennbrowser_click {text:"Allow"}→ the URL flips tolocalhost:<port>/fusion-aps/callback?code=…and the bridge's listener captures the token. - Poll
fusion_aps_statusuntilsignedIn:true. Done — APS search is fast and never touches Fusion's main thread.
The BEST sign-in path: the user's NATIVE Chrome/Edge via ABE (adom-browser-extension)
Autodesk's OTP/2FA and its "which profile is signed in" problem vanish if we drive the user's
OWN browser that is ALREADY logged into Autodesk. That is what ABE (adom-browser-extension) is
for: it exposes nbrowser_* verbs that open a URL in the user's real Chrome/Edge profile.
Recommend ABE first, and hand-hold the install if it's missing:
- Check: does
adom-desktop --target <laptop> nbrowser_readiness '{}'succeed? If not, ABE isn't installed. - Tell the user (honestly): "The smoothest Autodesk sign-in drives your own Chrome/Edge that's already logged in, no password typing, no OTP races. That needs the Adom Browser Extension (ABE). Let me walk you through installing it, one time."
- Point them to the install: https://wiki.adom.inc/adom/adom-browser-extension and follow the
installing-the-extensionsteps (load the MV3 extension, approve the native-host). Do as much as you can drive for them; only ask for the clicks Chrome forces a human to make. - Once ABE is live:
fusion_aps_signinreturnsneedsExtensionOpenwith anauthUrl; open it vianbrowser_open_windowin their signed-in profile; the bridge's localhost listener captures the token; pollfusion_aps_statusuntilsignedIn:true. Thenfusion_aps_set_browser {how: "extension"}so every future sign-in reuses that exact profile.
Fallback only if ABE truly can't be installed: fusion_aps_signin {allowDefaultBrowser:true}
(OS default browser) and drive the OTP per this skill.
Say the honest WHY (apologize, then reassure)
Autodesk gives no fast Fusion file-search API; the only in-app option takes 30+ minutes and can crash Fusion, so it's now disabled. APS (server-indexed) is the one thing that works. The cost is a one-time OAuth sign-in. Tell the user that plainly, apologize for the friction, and reassure them: once it's set up, cloud search is instant and it stays signed in (auto-refresh). It is worth it.
---
name: fusion-aps-signin
description: Drive the Autodesk sign-in flow in the user's real browser to set up APS (Autodesk Platform Services) for the Fusion bridge's fusion_aps_* cloud search — open a dedicated browser window, foreground it, MONITOR the sign-in, and auto-retrieve + enter the emailed one-time passcode (OTP) via adom-google before it expires. Use when signing into Autodesk/APS, registering an APS app, configuring fusion_aps_search, or any "log me into Fusion/Autodesk for APS" request. Trigger words — aps signin, sign in to autodesk, autodesk otp, fusion aps login, register aps app, aps client id, fusion_aps_signin, autodesk verification code, link google account autodesk.
---
# Fusion / APS sign-in (driven, with auto-OTP)
Goal: get the user signed into **aps.autodesk.com** in their real browser so you can
register an APS app and configure the Fusion bridge's `fusion_aps_*` search. The hard
part is Autodesk's **email OTP**, which **expires fast** — the user may walk away ("get a
cup of coffee"), so you must **monitor** the flow and turn the code around in seconds.
All browser steps use the native-browser extension verbs (`nbrowser_*`) against the
AD-connected laptop: `adom-desktop --target <laptop> nbrowser_* '{...}'`.
## Working principles (non-negotiable)
- **DO IT YOURSELF. NEVER ask the user to do anything manually that you can do.** That is the
entire point of the Adom AI ecosystem — the AI drives, the user doesn't. Don't hand the
user a "go create the app and paste me the Client ID" cop-out; drive the whole flow
(open windows, fill forms, fetch the OTP, click through) to completion yourself. Only
surface a real decision (a genuine fork) — never offload mechanical work.
- **NEVER navigate the user's CURRENT page/window away from them** — that hijacks their live
work (e.g. their Edge tab) and is unacceptable. **ALWAYS open a NEW window**
(`nbrowser_open_window {url}`) for whatever you need and drive ONLY that window's
`sessionId`. Opening your own windows and driving them is expected; reusing/navigating a
window the user is viewing is not. `desktop_bring_to_front` to surface a window for the
user is fine.
## Golden rules (learned the hard way)
1. **OTP expires in ~a few minutes. Be FAST.** Don't go fetch-and-think between resend and
entry — fetch the code and enter it in the same burst. We burned the 1st code dithering;
3rd round worked by resending and entering immediately.
2. **MONITOR the sign-in, don't fire-and-forget.** Poll the page state every few seconds
(the user may step away). Detect each transition: email → OTP → "code expired" →
"account already exists" → "linked" → portal. Never assume; re-read the page.
3. **Open a DEDICATED browser window** with `nbrowser_open_window` and **target it by
`sessionId`** in every `nbrowser_eval/type/click`. The extension **refuses to drive PWA /
installed-app windows** (e.g. "Hydrogen - Chat") and `nbrowser_eval` defaults to the
foreground tab — which is often the wrong (PWA) window.
4. **Foreground it with `desktop_bring_to_front`** (the AD verb) so the user can see/act on
the login. `nbrowser_focus_window` is NOT implemented.
5. **Proactively use adom-google.** Autodesk emails the OTP — you can read it via the
`adom-google` Gmail API passthrough. If adom-google isn't set up, TELL the user it exists
and offer to set it up (`adom-google auth`) so you can fetch the code for them. Gmail for
Adom = **[email protected]** (work account).
## Step-by-step
### 1. Open + foreground a dedicated window at the APS portal
```
adom-desktop --target <laptop> nbrowser_open_window '{"url":"https://aps.autodesk.com/myapps/"}'
# capture sessionId (e.g. s29) from the result; use it in EVERY later call
adom-desktop --target <laptop> desktop_bring_to_front '{...the browser window...}' # so the user sees it
```
Read state (always pass the sessionId):
```
nbrowser_eval '{"sessionId":"s29","expression":"JSON.stringify({url:location.href,title:document.title,body:document.body.innerText.slice(0,300)})"}'
```
If `location.href` is `signin.autodesk.com`, the profile has **no active Autodesk session** —
the user must start sign-in (enter email, or an SSO button). You won't type their password.
### 2. Monitor for the OTP screen
Poll `nbrowser_eval` every ~3-5s. The OTP page title is **"Linkable email OTP - Autodesk"**
with six single-char boxes `input[name=pin-1..pin-6]` and body "Enter the code from your
email. … Email sent."
### 3. Fetch the freshest OTP from Gmail (adom-google)
Check auth first: `adom-google status` (need a refresh token + gmail scope). Then:
```bash
# list newest Autodesk passcode mail (strip the leading "HTTP 200 ..." line)
MID=$(adom-google api "https://gmail.googleapis.com/gmail/v1/users/me/messages" \
-q "q=from:autodesk subject:passcode newer_than:1h" -q "maxResults=1" \
| tail -n +2 | python3 -c "import sys,json;print(json.load(sys.stdin)['messages'][0]['id'])")
# get it, pull the 6-digit code from the snippet ("Code: 205753")
adom-google api "https://gmail.googleapis.com/gmail/v1/users/me/messages/$MID" -q "format=full" \
| tail -n +2 | python3 -c "import sys,json,re;d=json.load(sys.stdin);print(re.search(r'Code:\s*(\d{6})',d['snippet']).group(1))"
```
Always take the **newest** message (the email footer also contains `000000`/`212121` noise —
match `Code:\s*(\d{6})`, not any 6 digits).
### 4. Enter the code — digit-by-digit (boxes are maxlen-1, NO auto-advance)
Bulk-typing the whole string only fills box 1. Focus each box, type its digit:
```bash
for i in 1 2 3 4 5 6; do
D=$(echo "$CODE" | cut -c$i)
nbrowser_eval '{"sessionId":"s29","expression":"document.querySelector('input[name=pin-'$i']').focus()"}'
nbrowser_type '{"sessionId":"s29","text":"'$D'"}'
done
nbrowser_click '{"sessionId":"s29","text":"Next"}'
```
Verify before submitting: read `[...].map(i=>i.value).join("")` == the code.
### 5. If "This code has expired" → resend + redo FAST
```
nbrowser_click '{"sessionId":"s29","text":"Resend"}'
# wait ~12s, fetch the NEWEST code (step 3), enter immediately (step 4)
```
### 6. "Account already exists" (Google-federated account)
Body: "An Autodesk account already exists with the email … sign in with Google … link …".
Click **"Link Google account"**. If the Google session is already active in Chrome it links
instantly ("Google account linked … Continue in 5 seconds") and lands in the portal — no
account picker. If a Google picker appears, pick **[email protected]**.
### 7. First-time APS → accept Terms of Service
First portal visit shows "Welcome aboard! … accept our Terms of Service". Accept it.
### 7.5 Developer-profile form (REQUIRED before you can create an app — you must fill it)
First-time APS gates app creation behind a one-time **developer/company profile** at
`https://aps.autodesk.com/myapps/create` ("Ready for next steps?"). YOU fill it from the
user's profile memory (`user_profile.md` — company, website, address). Fields seen:
`company`, `website`, `country`, `stateProvince`, `city`, `postalCode` (plain text) and
`roleId`, `accountPurpose` (**MUI comboboxes**) + a `tosAgreed` checkbox.
- Plain text: set via the native value setter + dispatch `input`+`change`+`blur` (MUI only
enables Submit after these fire):
```
nbrowser_eval set vals {company:"Adom Industries, Inc.",website:"https://adom.inc",
city:"Fort Worth",stateProvince:"TX",postalCode:"76177"} // country prefills "US"
```
- Comboboxes — can't just set `.value`; click to open, then **click the option by text**
(click-by-text finds it even when not in the visible top-N; typing to filter often does
NOT work). The fields and good picks for Adom:
- `roleId` = **Business owner/Entrepreneur** (John is the founder)
- `accountPurpose` = **Business**
- **Industry (select up to 3)** — REQUIRED, and it's the one that silently blocks Submit.
It has NO `name` attr (MUI multiselect) — find it by its label "Industry (select up to 3)"
(map each input to its nearest ancestor's label text + getBoundingClientRect, then click
the field's center coords). Pick **Industrial machinery** (Adom = PCB/electronics mfg).
- Tick `tosAgreed` (click the "I agree to the Autodesk Platform Services" label). **It
re-resets to false after combobox interactions / re-renders — re-verify it's checked right
before Submit.**
- **Submit silently no-ops while ANY required field is invalid, with the button still
`enabled` and NO scrape-able error.** When Submit won't advance, **take a screenshot
(`nbrowser_screenshot {sessionId}`) and READ it** — inline "Please fill out this field"
tooltips (e.g. the empty Industry box) only show visually, not in the DOM you're scraping.
This is the fastest way to find a missed required field.
- Field coords from `getBoundingClientRect` are in PAGE space (what `nbrowser_click {x,y}`
wants) — do NOT use screenshot pixel coords (the shot is downscaled, different origin).
Known profile values (Adom / John): Company "Adom Industries, Inc.", Website https://adom.inc,
4400 Alliance Gateway Fwy, Fort Worth, TX 76177, US, [email protected].
### 7.55 Get the FREE APS plan (drive the whole checkout yourself — incl. the card)
Newer APS gates app creation behind a **developer hub**, which requires an **APS plan**. The
**Free tier is $0** but Autodesk requires a **payment method "to verify identity"** (no charge).
**The AI drives 100% of this**, including entering the card. Live-verified flow:
1. New window → `https://aps.autodesk.com/hubs/` → the "It seems you don't have a hub yet"
page → **Step 1 "Get an APS plan" → click "View options"** (or go straight to
`https://www.autodesk.com/products/autodesk-platform-services/overview`).
2. On the pricing tiers (3 columns: **Free** | Prepay $99 | Pay-as-you-go), click the
**leftmost "Add to Cart"** = the **Free** tier. (Get all `Add to Cart` rects, sort by x,
take the smallest — Free is the left column. NEVER click the paid columns.)
3. Cart drawer shows **"APS Free — $0.00", SUBTOTAL $0.00**. Click **Check out**.
4. `checkout.autodesk.com` — a 3-step accordion: **Cart → Customer details → Payment**, with
**Order summary TOTAL $0.00**. Click **Continue**; an abandon-cart modal ("Don't leave your
cart behind!") may pop — click **CONTINUE CHECKOUT**, then **Continue** again. Customer
details auto-fill from the Autodesk account. It lands open on **Payment**.
5. ⚠️ **VERIFY TOTAL = $0.00 before doing anything in Payment.** If it's ever nonzero, STOP —
never proceed (hard rule: no user is ever charged).
6. **Payment — almost always a card is ALREADY on file (no card entry needed).** **Almost
every Adom user has a PAID Fusion 360 subscription**, which means Autodesk already has their
payment method on file. So the Payment step will typically show an **existing card** —
**SELECT it** and move on. The AI completes this with **zero** card handling and zero user
input. Only in the rare case of NO card on file do you fall back to collecting one from the
user (their own card, ID-verification only; **TREAT AS SENSITIVE — never echo/store/log
it**). Either way, then click **Submit order** (agrees to Autodesk's $0 Online Purchase
Terms; auto-renews at $0).
7. After the $0 order confirms, continue to the hub.
### 7.6 Create the developer hub (manage.autodesk.com)
Per Autodesk docs: `manage.autodesk.com` → **Products and Services → Hubs → Create hub** →
select **APS developer hub** → enter a name (e.g. "Adom") + optional description → **Create
and Activate**. (The account may already show an org hub named "Adom" at
`manage.autodesk.com/hubs-list`; if a usable APS developer hub already exists, use it.)
If routes 404 / loop, open a FRESH window and retry — don't blind-click, and don't offload it.
### 7.7 (was 7.6) Register the app — drive it, don't hand it off
After the profile, newer APS routes app creation through a **developer hub**:
`/myapps/create` → `/hubs/@personal/applications/create` may 404 ("Not found"), and `/myapps`
redirects to "you don't have a hub yet" with a **Create hub** button that bounces to
`manage.autodesk.com/hubs-list` (a DIFFERENT portal; the account may already list an org hub
like "Adom"). This area is non-linear and account-structural. If it 404s / loops, **don't blind-click** —
open a FRESH window, reload, and work the hub→app path yourself (create/select the hub, then
the app). Drive it to a Client ID yourself; do NOT offload it to the user. Once you have the
Client ID, `fusion_aps_set_client_id` → `fusion_aps_signin` → `fusion_aps_search`.
### 8. Register the APS app (then configure the bridge)
Create App → enable **Data Management API** → **Callback URL =
`http://localhost:8917/fusion-aps/callback`** (must match the bridge's `REDIRECT_URI`
EXACTLY) → create → copy the **Client ID** (PKCE = public client; the secret is unused).
Then:
```
adom-desktop --target <laptop> fusion_aps_set_client_id '{"clientId":"<CLIENT_ID>"}'
adom-desktop --target <laptop> fusion_aps_signin '{}' # opens browser; bg listener on :8917 stores the token
# poll fusion_aps_status until {"data":{"signedIn":true,"tokenLive":true}}
adom-desktop --target <laptop> fusion_aps_search '{"query":"<part name>"}'
```
## LIVE-VERIFIED end-to-end run (2026-06-26, Adom org) — the exact sequence
This whole flow was driven live and works. Replicate it per org:
1. **Sign in** (§1–7): new window → aps.autodesk.com → email → OTP from Gmail (adom-google) →
"Account already exists" → **Link Google account** → lands in APS.
2. **Dev profile** (§7.5): fill from user profile; Industry is REQUIRED (screenshot to catch
it); role=Business owner, purpose=Business, Industry=Industrial machinery; Submit.
3. **Free plan** (§7.55): aps.autodesk.com/hubs → "Get an APS plan" → View options → pricing:
**leftmost "Add to Cart" = Free** → cart shows "APS Free $0.00" → Check out →
checkout.autodesk.com 3-step accordion (Cart→Customer details→Payment), **TOTAL $0.00** →
Continue (+ "CONTINUE CHECKOUT" on the abandon-cart modal) → **Payment step almost always
already shows an existing card on file** (Fusion subscribers) ✅ → **Submit order** → "Order
Confirmation". $0, existing card, no card entry.
4. **APS Developer Hub** (§7.6): manage.autodesk.com → Products and services → **Hubs** →
**Create hub ▾ → APS Developer Hub** → name "Adom APS" → **Create & Activate** (takes a
minute). NOTE: this is a CREDENTIAL container with ZERO files — NOT the team's data hub.
5. **Register the app** (§7.7): aps.autodesk.com/myapps → hub now selectable → **Create
application** → Name "Adom Fusion Bridge" → app-type = **"Desktop, Mobile, Single-Page App"**
(radio value `native` = **Authorization Code with PKCE**) → Create. ⭐ PKCE app type =
**"Paid APIs are unavailable"** → structurally can't be charged (1st never-charge lock).
6. **Callbacks + APIs**: in App settings → Callback URL section, the default is
`http://localhost:8080/`. Click **"+ Add URL" 5×** (→ 6 fields), fill all 6 with the
bridge's registered set (`all_registered_callbacks()`): localhost+127.0.0.1 × ports
8917/8918/8920. API Access defaults to all free APIs incl. **Data Management** (keep). Click
**Save changes** (find it by coords — click-by-text can hit the wrong element).
7. **Client ID**: App settings → Client Credentials → copy the **Client ID** (public PKCE id;
NO secret). Extract from the DOM, not a pixel read.
8. **Wire + sign in**: `fusion_aps_set_client_id {clientId}` → `fusion_aps_signin` (bridge
opens consent, listens on the bound port) → poll `fusion_aps_status` until `signedIn:true` →
`fusion_aps_search {query}` → prove it returns files from the team's shared **Main** folder.
## Never-charge — TRIPLE locked (don't weaken any of these)
1. The **PKCE app type cannot use paid APIs** (Autodesk-enforced).
2. The bridge's **free-endpoint allowlist** (`/project/v1/`, `/data/v1/` only).
3. The bridge's **monthly hard cap** (fails closed). Card on file = identity verification only.
## Port choice for the callback
Check availability LIVE on the box (no AD verb exists): `python` bind-test on 127.0.0.1 +
`netsh int ipv4 show excludedportrange protocol=tcp`. 8917/8918/8920 verified free + outside
Windows reserved ranges (5357, 27339, 50000-50059). The box runs ~67 listeners — don't assume.
## Gotchas
- `nbrowser_eval/type/click` without `sessionId` hit the foreground tab → often the wrong
(PWA) window. Always pass the dedicated `sessionId`.
- `adom-google api` prints a `HTTP 200 GET …` header line before the JSON — `tail -n +2`.
- The bridge relay only forwards `output/data/success/error/_hint` — irrelevant here but
relevant when reading `fusion_aps_*` results (fields live under `data`).
- Don't auto-enter the user's Autodesk **password** or drive their Google **consent** —
identity decisions are theirs; automate the OTP + form-filling, not the credentials.
## ⭐ APS AUTH-001 self-heal — the app lost its Data Management API product (verified live 2026-07-14)
**Symptom:** `fusion_aps_signin` now returns `errorCode: "aps_app_missing_product"` (the bridge probes
the /authorize endpoint server-side and detects it BEFORE opening a browser), or you see the raw
`{"errorCode":"AUTH-001","developerMessage":"The client_id specified does not have access to the api
product"}` on the authorize page. It means the org's APS app at aps.autodesk.com/myapps lost its **Data
Management API** product entitlement (it can work for months, then break). The app config often still
*looks* correct — the fix is a forced re-commit.
**Recovery (drive with ABE/nbrowser — install the extension FIRST if it isn't; coordinate-clicking the
portal is fragile and Edge crashes):**
1. `nbrowser_open_window {sessionId, thread, purpose, profile:<warm Edge/Chrome>, url:"https://aps.autodesk.com/myapps/"}` → open the app whose Client ID matches (in the org's "Adom APS" dev hub).
2. App-settings → **API Access**: confirm **Data Management API** is checked. Then force a re-commit —
`nbrowser_eval` a click on the **visible** Save button:
`(()=>{var b=[...document.querySelectorAll("button")].filter(x=>/save changes/i.test(x.textContent)&&x.offsetParent!==null);if(b.length)b[0].click();return JSON.stringify({n:b.length})})()`
(the bare text "Save changes" matches ~9 hidden duplicates, so `nbrowser_click {text}` is ambiguous —
use the offsetParent filter). If Save is disabled, open the API dropdown and toggle one unneeded API
off first to dirty the form.
3. **Wait 1–3 min** for Autodesk to propagate the entitlement.
4. Retry `fusion_aps_signin` → it now reaches the **consent** screen ("… is requesting permission …
View/Manage/Write your data … **Allow**"). `nbrowser_navigate` the session to the fresh `authUrl`,
then `nbrowser_click {text:"Allow"}` → the URL flips to `localhost:<port>/fusion-aps/callback?code=…`
and the bridge's listener captures the token.
5. Poll `fusion_aps_status` until `signedIn:true`. Done — APS search is fast and never touches Fusion's
main thread.
## The BEST sign-in path: the user's NATIVE Chrome/Edge via ABE (adom-browser-extension)
Autodesk's OTP/2FA and its "which profile is signed in" problem vanish if we drive the user's
OWN browser that is ALREADY logged into Autodesk. That is what ABE (adom-browser-extension) is
for: it exposes `nbrowser_*` verbs that open a URL in the user's real Chrome/Edge profile.
**Recommend ABE first, and hand-hold the install if it's missing:**
1. Check: does `adom-desktop --target <laptop> nbrowser_readiness '{}'` succeed? If not, ABE isn't
installed.
2. Tell the user (honestly): "The smoothest Autodesk sign-in drives your own Chrome/Edge that's
already logged in, no password typing, no OTP races. That needs the Adom Browser Extension
(ABE). Let me walk you through installing it, one time."
3. Point them to the install: https://wiki.adom.inc/adom/adom-browser-extension and follow the
`installing-the-extension` steps (load the MV3 extension, approve the native-host). Do as much
as you can drive for them; only ask for the clicks Chrome forces a human to make.
4. Once ABE is live: `fusion_aps_signin` returns `needsExtensionOpen` with an `authUrl`; open it
via `nbrowser_open_window` in their signed-in profile; the bridge's localhost listener captures
the token; poll `fusion_aps_status` until `signedIn:true`. Then `fusion_aps_set_browser {how:
"extension"}` so every future sign-in reuses that exact profile.
Fallback only if ABE truly can't be installed: `fusion_aps_signin {allowDefaultBrowser:true}`
(OS default browser) and drive the OTP per this skill.
## Say the honest WHY (apologize, then reassure)
Autodesk gives no fast Fusion file-search API; the only in-app option takes 30+ minutes and can
crash Fusion, so it's now disabled. APS (server-indexed) is the one thing that works. The cost is
a one-time OAuth sign-in. Tell the user that plainly, apologize for the friction, and reassure
them: once it's set up, cloud search is instant and it stays signed in (auto-refresh). It is
worth it.