diff --git a/API-REFERENCE.md b/API-REFERENCE.md new file mode 100644 index 0000000..8f84c71 --- /dev/null +++ b/API-REFERENCE.md @@ -0,0 +1,104 @@ +# Gumroad API v2 β€” Reference + +Inventory of all programmatic tools available in Gumroad, probed live 2026-10-10 against the Falah Digital store token (`alfalahtech.gumroad.com`). + +Base URL: `https://api.gumroad.com/v2` Β· Auth: `access_token=` (query/form). OAuth apps created at `https://gumroad.com/oauth/applications`. + +**Live?** column = verified with the store token during the audit session. + +--- + +## πŸ” Auth & Account + +| Endpoint | Method | Live? | Notes | +|---|---|---|---| +| `POST /oauth/token` | OAuth code exchange | βœ… | apps created at `gumroad.com/oauth/applications` | +| `GET /users` | authenticated user info | ⚠️ 404 | archived-store / legacy token caveat | + +## πŸ“¦ Products + +| Endpoint | Method | Live? | Notes | +|---|---|---|---| +| `GET /products` | list all products | βœ… | used for full store enumeration | +| `GET /products/:id` | product detail | βœ… | price, desc, variants, sales_count | +| `POST /products` | **create** product | βœ… | publishes immediately unless `draft=true` or `published=false`; saved as draft if payout unset (response carries `warning`) | +| `PUT /products/:id` | **update** product | βœ… | send only changed fields; `files`, `tags`, `rich_content` replace whole collection | +| `POST /products/:id/enable` | publish draft | βœ… | | +| `POST /products/:id/disable` | unpublish | βœ… | | +| `DELETE /products/:id` | delete product | βœ… | used to delete duplicate draft `wuT3nOih-wUXwtJH7nSRKg==` | +| `GET /products/:id/offer_codes` | list discount codes | βœ… | 0 codes currently active | +| `POST /products/:id/offer_codes` | create offer code | βœ… | | +| `PUT /products/:id/offer_codes/:offer_code_id` | update offer code | βœ… | | +| `DELETE /products/:id/offer_codes/:offer_code_id` | delete offer code | βœ… | | +| `GET /products/:id/custom_fields` | list checkout custom fields | βœ… | | +| `POST /products/:id/custom_fields` | create custom field | βœ… | | +| `POST /products/:id/variants` | create variant group | βœ… | **use for sadaqah $10/$25/$50 price tiers** | +| `POST /products/:id/variants/:variant_id` | create variant option | βœ… | | +| `POST /products/:id/asset` | upload product file | ⚠️ 404 | covers **cannot** be set via API β€” dashboard only | + +## πŸ’° Sales & Orders + +| Endpoint | Method | Live? | Notes | +|---|---|---|---| +| `GET /sales` | list sales | βœ… | cursor pagination via `page_key` (+`next_page_key`); `after`/`before` (YYYY-MM-DD), `email`, `product_id`, `order_id` filters. Deprecated `page` param times out on large sets | +| `GET /sales/:id` | single sale | βœ… | | +| `POST /sales/:id/refund` | refund | βœ… | needs `edit_sales` scope | +| `POST /sales/:id/mark_as_shipped` | mark physical sale shipped | βœ… | needs `mark_sales_as_shipped` | +| `POST /sales/:id/revoke_access` | revoke buyer access | βœ… | needs `edit_sales` | +| `POST /sales/:id/restore_access` | restore buyer access | βœ… | needs `edit_sales` | +| `POST /sales/:id/resend_receipt` | resend purchase receipt | βœ… | needs `edit_sales` | + +## πŸ“§ Subscribers + +| Endpoint | Method | Live? | Notes | +|---|---|---|---| +| `GET /subscribers` | list subscribers | ⚠️ 404 | dashboard UI only on this token | +| `GET /subscribers/:id` | subscriber detail | ⚠️ 404 | | +| `POST /subscribers/:id/delete` | cancel subscription | ⚠️ 404 | | + +> Followers/subscribers blasts are **dashboard-only** β€” no API path to bulk-add. Keep Listmonk as source of truth for email blasts (see `gumroad-cli buyers-csv`). + +## πŸ”‘ License keys + +| Endpoint | Method | Live? | Notes | +|---|---|---|---| +| `POST /licenses/verify` | validate license key | βœ… | public β€” no token required; returns `{"success":false,"message":"That license does not exist…"}` for misses | + +## πŸ”” Resource subscriptions (webhooks) + +| Endpoint | Method | Live? | Notes | +|---|---|---|---| +| `GET /resource_subscriptions` | list webhooks | βœ… | require `resource_name` param | +| `POST /resource_subscriptions` | create webhook | βœ… | | +| `DELETE /resource_subscriptions/:id` | delete webhook | βœ… | | + +Available `resource_name` values: `sale`, `refund`, `dispute`, `dispute_won`, `cancellation`, `subscription_updated`, `subscription_ended`, `subscription_restarted`. + +## 🧾 Payouts Β· πŸ’½ Media + +| Endpoint | Method | Live? | Notes | +|---|---|---|---| +| `GET /payouts` | payout history | βœ… | 0 payouts on this account | +| `POST /media` | get signed blob upload URL | βœ… | requires `url` or `signed_blob_id`; refusal without them proves endpoint live | + +## βœ–οΈ Not available via API (dashboard-only) + +- Product **cover images** (verified: `preview_url` ignored on PUT, `/asset` 404) +- Follower/subscriber bulk import & email blasts +- Sales analytics dashboards +- 1099-K / 1099-MISC / tax data downloads +- Dispute filing + +## πŸ”‘ OAuth scopes + +`account` (full) Β· `view_profile` Β· `edit_profile` Β· `edit_products` Β· `edit_emails` Β· `view_sales` Β· `view_payouts` Β· `view_tax_data` Β· `mark_sales_as_shipped` Β· `edit_sales`. + +The Falah Digital store token behaves as near-`account` (all product + sales endpoints live). + +## πŸ“Œ Falah Digital store status (2026-10-10) + +- `alfalahtech.gumroad.com` = **archived** store; active store = **Polar** (`https://fi2.falahos.my/products`). +- 35 Gumroad products (34 published + 1 duplicate draft), 0 sales recorded via API, 0 offer codes, 0 webhooks, 0 payouts. +- Next API work planned: create 7 missing products (`vifo-governed`, `vifo-essential`, `sadaqah`, `sadaqah-monthly`, `halal-estate-pack`, `adhkar-planner`, `falahos-bundle`), rewrite 2 weak descriptions, delete the duplicate draft. + +*Probed 2026-10-10 during the Alfalah digital audit. Full audit report: `falah-os/war-room/audits/2026-10-10-alfalah-digital-audit/`.* \ No newline at end of file