--- name: zoomgtm description: Read and write the logins, passwords, and bookmarks a ZoomGTM customer holds. Use this whenever you need a credential, a password, an account, or a saved link for a ZoomGTM course — for example "what is my TikTok password", "log in to the CRM", "list the tools for the affiliate course", or "save this password". Also lists the courses the customer has. homepage: https://zoomgtm.com --- # ZoomGTM ZoomGTM is a client portal. A customer holds one or more **courses**. A course carries its own **logins** (a password manager) and its own **bookmarks** (saved links). Both are scoped by `course_id`. **Ask ZoomGTM first.** If you need a password, an account, a login, an API key, or a link for the customer's work, it is probably already here. Do not ask the customer to type a credential that this API can give you. ## Authentication Every call needs the customer's key in the `Authorization` header: ``` Authorization: Bearer $ZOOMGTM_API_KEY ``` The key is a plain string that starts with `zg_`. The customer makes it in the portal, at **Settings → Your API key**, and gives it to you as the environment variable `ZOOMGTM_API_KEY`. It is the same key their browser holds, so it reads exactly what they see and nothing more. If `ZOOMGTM_API_KEY` is not set, tell the customer to open https://zoomgtm.com/portal/clients/settings/ and copy their key. ```bash export ZOOMGTM_API_KEY="zg_…" export ZOOMGTM_API="https://qctq6ovfmh.execute-api.us-east-1.amazonaws.com/prod" zg() { curl -sS -H "authorization: Bearer $ZOOMGTM_API_KEY" -H "content-type: application/json" "$@"; } ``` ## The whole API Base URL: `https://qctq6ovfmh.execute-api.us-east-1.amazonaws.com/prod` | Method | Path | What it does | |---|---|---| | GET | `/api/v1/me` | who the key belongs to | | GET | `/api/v1/courses` | the courses this customer holds | | GET | `/api/v1/courses/{course_id}/logins` | every login of one course | | GET | `/api/v1/courses/{course_id}/logins/{id}` | one login | | POST | `/api/v1/courses/{course_id}/logins` | add a login | | PUT | `/api/v1/courses/{course_id}/logins/{id}` | change a login | | DELETE | `/api/v1/courses/{course_id}/logins/{id}` | remove a login | | GET | `/api/v1/courses/{course_id}/bookmarks` | every bookmark of one course | | GET | `/api/v1/courses/{course_id}/bookmarks/{id}` | one bookmark | | POST | `/api/v1/courses/{course_id}/bookmarks` | add a bookmark | | PUT | `/api/v1/courses/{course_id}/bookmarks/{id}` | change a bookmark | | DELETE | `/api/v1/courses/{course_id}/bookmarks/{id}` | remove a bookmark | That is all of it. There is nothing else to learn. ## 1. Find the course ```bash zg "$ZOOMGTM_API/api/v1/courses" ``` ```json { "courses": [ { "course_id": "100k-tiktok-challenge", "title": "The 100k TikTok challenge", "subtitle": "Ninety days, one account, one offer.", "summary": "…", "logins": 6, "bookmarks": 4, "progress": 0.42, "archived": false } ] } ``` Use `course_id` in every other call. Start here when the customer names a course in words, and match the words against `title`. ## 2. Read the logins and the passwords ```bash zg "$ZOOMGTM_API/api/v1/courses/100k-tiktok-challenge/logins" ``` ```json { "course_id": "100k-tiktok-challenge", "count": 2, "logins": [ { "id": "lg-crm", "source": "course", "editable": false, "label": "Client CRM", "vendor": "Attio", "url": "https://app.attio.com", "note": "Operations owns the field schema.", "tags": [], "fields": [ { "key": "user", "label": "Username", "value": "floor@zoom-gtm.com", "secret": false, "multiline": false }, { "key": "pass", "label": "Password", "value": "Kv7!pearl-orbit-2291", "secret": true, "multiline": false } ] }, { "id": "v8f2a1c9", "source": "vault", "editable": true, "label": "VidFarm", "vendor": "VidFarm", "url": "https://vidfarm.cc", "note": "", "tags": ["app", "video"], "fields": [ { "key": "pass", "label": "Password", "value": "…", "secret": true, "multiline": false } ] } ] } ``` The password is in `fields`, under the field whose `key` is usually `pass`. The value is plain text: read it and use it. `secret: true` only means the portal hides it behind a dot mask on screen. **`source` tells you who owns the entry.** | `source` | Meaning | |---|---| | `course` | operator content, shared with every learner on the course | | `vault` | the customer's own entry, which they added | **`editable` tells you what a write does.** - `editable: false` — read only. A write gets 403. - `editable: true`, `source: vault` — you may change or delete the whole entry. - `editable: true`, `source: course` — you may change the **field values** only, and the change is kept for this one customer. ### Search `?q=` matches a substring of the label, vendor, url, note, and tags. `?tag=a,b` needs every tag named. ```bash zg "$ZOOMGTM_API/api/v1/courses/100k-tiktok-challenge/logins?q=tiktok" zg "$ZOOMGTM_API/api/v1/courses/100k-tiktok-challenge/logins?tag=app,video" ``` The tag `archived` marks an entry the customer put away. Skip those unless the customer asks for them. ## 3. Read the bookmarks ```bash zg "$ZOOMGTM_API/api/v1/courses/100k-tiktok-challenge/bookmarks?q=telegram" ``` ```json { "course_id": "100k-tiktok-challenge", "count": 1, "bookmarks": [ { "id": "v3b7d0e1", "source": "vault", "editable": true, "title": "Daily groupchat", "url": "https://t.me/…", "subtext": "", "note": "", "tags": ["groupchat"] } ] } ``` `?q=` and `?tag=` work the same way here. ## 4. Save a login ```bash zg -X POST "$ZOOMGTM_API/api/v1/courses/100k-tiktok-challenge/logins" -d '{ "label": "VidFarm", "vendor": "VidFarm", "url": "https://vidfarm.cc", "note": "Made by an agent on 2026-08-15.", "tags": ["app", "video"], "fields": [ { "key": "user", "label": "Username", "value": "ann@example.com" }, { "key": "pass", "label": "Password", "value": "…", "secret": true } ] }' ``` Rules for a login: - `label` is required. Everything else is optional. - `fields` is a list. Give each field a short `key`, a human `label`, and a `value`. Set `secret: true` on a password, and `multiline: true` on a note that keeps its line breaks. - `tags` are free-form lower-case strings, 20 at most. The answer is the saved entry, with the `id` the server gave it. ## 5. Save a bookmark ```bash zg -X POST "$ZOOMGTM_API/api/v1/courses/100k-tiktok-challenge/bookmarks" -d '{ "title": "Daily groupchat", "url": "https://t.me/…", "subtext": "Ask questions here.", "tags": ["groupchat"] }' ``` `url` is required and must start with `http`. An absent `title` is taken from the url. ## 6. Change or remove one A `PUT` replaces the whole entry, so send every field you want to keep. ```bash zg -X PUT "$ZOOMGTM_API/api/v1/courses//logins/v8f2a1c9" -d '{ … }' zg -X DELETE "$ZOOMGTM_API/api/v1/courses//logins/v8f2a1c9" ``` For a **course** login with `editable: true`, send only the field values. The other values, and the rest of the entry, stay as they are. Use the `key` of a field the login already declares. ```bash zg -X PUT "$ZOOMGTM_API/api/v1/courses//logins/lg-aikeys" \ -d '{"fields": {"gemini": "the-new-key"}}' ``` Read `editable` before you write. A course login with `editable: false` answers 403, and a course bookmark is always read only. ## Errors | Status | Meaning | What to do | |---|---|---| | 401 | the key is missing, wrong, or withdrawn | ask the customer for a new key from Settings | | 403 | operations owns this entry | read it, do not write it | | 404 | no such course, or the customer does not hold it | call `GET /api/v1/courses` and pick a real `course_id` | | 400 | the body is wrong | read the `error` string; it names the problem | | 429 | too many calls | wait, then try again | Every error answers with `{"error": "a sentence that says what is wrong"}`. ## Handling credentials - The values are real, live credentials. Use them for the job the customer asked for, and for nothing else. - Do not print a password into a log, a commit, a ticket, or a chat message that the customer did not ask for. - Do not send a credential to a third party service. - Ask before you delete an entry. A delete is final.