Create a product demo in your own style...
" } ``` `status` is one of `draft`, `active`, `paused`, `finished`. `brief` is included on `show` only and is rendered HTML (rich text). ## List [Section titled “List”](#list) ```http GET /organizations/:organization_id/campaigns.json ``` Returns the brand’s campaigns (subject to your role’s policy scope). Paginated. ## Show [Section titled “Show”](#show) ```http GET /organizations/:organization_id/campaigns/:id.json ``` Returns one campaign including the rendered `brief` HTML. Sets an ETag. ## Create [Section titled “Create”](#create) ```http POST /organizations/:organization_id/campaigns.json { "campaign": { "name": "Summer UGC Campaign", "website": "https://example.com/product", "content_type": "ugc", "category": "product", "currency": "usd", "cpm_amount": 500, "min_payout_amount": 1000, "max_payout_amount": 10000, "base_reward_amount": 0, "platform_ids": ["youtube", "tiktok"], "countries": ["US", "GB"], "brief": "Create a product demo in your own style...
" } } ``` Creates a draft campaign. Requires a write-scoped token and an **admin** role on the brand. Returns `201 Created` with the new campaign. If you omit optional fields, the server fills them from the campaign form defaults where possible. Budget totals always start at zero on create; funding happens separately. ## Update [Section titled “Update”](#update) ```http PATCH /organizations/:organization_id/campaigns/:id.json { "campaign": { "name": "Updated campaign name", "cpm_amount": 650 } } ``` Returns `200 OK` with the updated campaign. Once a campaign has been published, only the same fields allowed in the web UI remain writable; financial fields are no longer accepted. ## Delete [Section titled “Delete”](#delete) ```http DELETE /organizations/:organization_id/campaigns/:id.json ``` Returns `204 No Content`. Fails if the campaign is no longer a draft or already has fundings. ## State transitions (not yet exposed via JSON) [Section titled “State transitions (not yet exposed via JSON)”](#state-transitions-not-yet-exposed-via-json) `POST .../publish`, `.../pause`, and `.../resume` still redirect today. JSON support is not rolled out for those actions yet. ## Errors [Section titled “Errors”](#errors) | Code | When | | ----- | ------------------------------------------------------------ | | `401` | Missing token, or read token attempting a write | | `403` | You’re authenticated but your role can’t perform this action | | `404` | Campaign or org does not exist *for you* | | `422` | Validation failed | # Collabs > A collab is a brand's brief that creators can apply to. Organization-scoped — the URL identifies the brand. A collab is a brand’s brief that creators can apply to. Org-scoped: the URL identifies the brand. ## Resource shape [Section titled “Resource shape”](#resource-shape) ```json { "id": 9, "name": "Spring Lipstick Drop", "state": "published", "currency": "usd", "countries": ["US", "CA"], "website": "https://example.com/lipstick", "require_spark_ads": true, "requires_product_shipment": false, "submissions_count": 24, "completed_count": 6, "published_at": "2026-04-15T10:00:00Z", "created_at": "2026-04-01T10:00:00Z", "updated_at": "2026-05-01T10:00:00Z", "url": "https://hypemarket.ai/organizations/3/collabs/9.json", "banner_image_url": "https://hypemarket.ai/rails/active_storage/...", "brief": "Show the lipstick in a get-ready-with-me video...
" } ``` `state` is one of `draft`, `submitted_for_review`, `published`, `paused`. `brief` is included on `show` only and is rendered HTML (rich text). ## List [Section titled “List”](#list) ```http GET /organizations/:organization_id/collabs.json ``` Returns the brand’s collabs (subject to your role’s policy scope). Paginated. ## Show [Section titled “Show”](#show) ```http GET /organizations/:organization_id/collabs/:id.json ``` Returns one collab including the rendered `brief` HTML. Sets an ETag. ## Create [Section titled “Create”](#create) ```http POST /organizations/:organization_id/collabs.json { "collab": { "name": "Spring lipsticks", "website": "https://example.com/lipstick", "currency": "eur", "countries": ["FR", "DE"], "require_spark_ads": true, "requires_product_shipment": false, "brief": "Show the lipstick in a get-ready-with-me video...
" } } ``` Creates a draft collab. Requires a write-scoped token and an **admin** role on the brand. You can send a `collab` payload to override the brand defaults. Any omitted fields fall back to the brand’s defaults (for example default countries and brief template). If you omit `collab` entirely, the server still creates a draft from defaults only. To pre-fill from a product page, pass a top-level `website` query param such as `?website=https://...`. That prefill flow is primarily intended for the web UI and may replace generated fields such as `name`, `brief`, `countries`, `website`, and `banner_image`. ## Update [Section titled “Update”](#update) ```http PATCH /organizations/:organization_id/collabs/:id.json { "collab": { "name": "Updated name", "currency": "eur", "countries": ["FR", "DE"], "brief": "New brief…
" } } ``` Returns `200 OK` with the updated collab. To remove an existing banner, pass `purge_banner_image: "1"`. ## Delete [Section titled “Delete”](#delete) ```http DELETE /organizations/:organization_id/collabs/:id.json ``` Returns `204 No Content`. Fails if the collab has approved submissions. ## State transitions (not yet exposed via JSON) [Section titled “State transitions (not yet exposed via JSON)”](#state-transitions-not-yet-exposed-via-json) `POST .../submit`, `.../pause`, `.../unpause` redirect today. JSON support is on the rollout list. ## Errors [Section titled “Errors”](#errors) | Code | When | | ----- | ------------------------------------------------------------ | | `401` | Missing token, or read token attempting a write | | `403` | You’re authenticated but your role can’t perform this action | | `404` | Collab or org does not exist *for you* | | `422` | Validation failed | # Memberships > The link between a user and a brand. Used to manage who's on the team and what role they hold. Organization-scoped. The link between a user and a brand. Org-scoped. Used to manage who’s on the team and what role they hold. ## Resource shape [Section titled “Resource shape”](#resource-shape) ```json { "id": 12, "role": "admin", "is_owner": true, "created_at": "2026-04-01T10:00:00Z", "updated_at": "2026-04-01T10:00:00Z", "user": { "id": 7, "name": "Yaro", "email": "yaro@example.com" } } ``` `role` is `member` or `admin`. `is_owner` is true for the brand owner — the owner cannot be removed or demoted. ## List [Section titled “List”](#list) ```http GET /organizations/:organization_id/members.json ``` Returns members of the brand, ordered admins-first. Paginated. ## Update [Section titled “Update”](#update) ```http PATCH /organizations/:organization_id/members/:id.json { "membership": { "role": "admin" } } ``` Requires admin role on the brand. Cannot demote the only remaining admin. Cannot demote the brand owner. ## Delete (remove member or leave) [Section titled “Delete (remove member or leave)”](#delete-remove-member-or-leave) ```http DELETE /organizations/:organization_id/members/:id.json ``` Removes the membership. If you remove yourself, you’ve left the brand. Cannot remove: * The brand owner * Yourself if you are the sole member * The only remaining admin Returns `204 No Content` on success, `422` with errors on a guarded failure. ## Errors [Section titled “Errors”](#errors) | Code | When | | ----- | ----------------------------------------------- | | `401` | Missing token, or read token attempting a write | | `403` | Authenticated but you’re not an admin | | `404` | Membership or brand does not exist *for you* | | `422` | Guard failed (last admin, owner demote, etc.) | # Notification settings > The authenticated user's push notification preferences. Toggle web/native push delivery without losing existing device subscriptions. The authenticated user’s push notification preferences. ## Resource shape [Section titled “Resource shape”](#resource-shape) ```json { "push_notifications_enabled": true, "push_subscription_count": 2 } ``` `push_subscription_count` is the number of devices currently subscribed for web push. Disabling notifications keeps subscriptions registered (so re-enabling is instant) but suppresses delivery. ## Show [Section titled “Show”](#show) ```http GET /me/notification_settings.json ``` ## Update [Section titled “Update”](#update) ```http PATCH /me/notification_settings.json { "push_notifications_enabled": true } ``` Requires a write-scoped token. Returns `200 OK` with the new state. ## Errors [Section titled “Errors”](#errors) | Code | When | | ----- | ----------------------------------------------- | | `401` | Missing token, or read token attempting a write | # Notifications > The authenticated user's notification inbox. Newest-first, paginated, type-discriminated. The authenticated user’s notification inbox. ## Resource shape [Section titled “Resource shape”](#resource-shape) ```json { "id": 88, "type": "Membership::JoinRequestReceivedNotifier", "params": { "user_name": "Yaro", "organization_name": "Acme" }, "record_type": "Membership::JoinRequest", "record_id": 42, "seen_at": "2026-05-05T08:30:00Z", "read_at": null, "created_at": "2026-05-05T08:00:00Z" } ``` `type` is the Noticed event class — use it to dispatch on the notification kind. `params` is event-specific. `record_type` / `record_id` point to the related resource. ## List [Section titled “List”](#list) ```http GET /me/notifications.json ``` Returns the user’s notifications, newest first. Excludes submission-message notifications (those are surfaced inline in the chat UI). Paginated — `Total-Count`, `Total-Pages`, etc. Note Unlike the HTML view, calling this endpoint does **not** mark notifications as seen. That side effect is UI-specific. ## Errors [Section titled “Errors”](#errors) | Code | When | | ----- | ------------- | | `401` | Missing token | # Organizations > A brand owned or co-administered by the authenticated user. Endpoints to list, show, create, update, and delete brands. A brand owned or co-administered by the authenticated user. ## Resource shape [Section titled “Resource shape”](#resource-shape) ```json { "id": 3, "name": "Acme Cosmetics", "privacy_setting": "public", "website": "https://acme.example.com", "created_at": "2026-04-01T10:00:00Z", "updated_at": "2026-05-01T10:00:00Z", "url": "https://hypemarket.ai/organizations/3.json", "logo_url": "https://hypemarket.ai/rails/active_storage/..." } ``` `privacy_setting` is one of `public`, `private`, `restricted`. `logo_url` is omitted when no logo is attached. ## List [Section titled “List”](#list) ```http GET /organizations.json ``` Returns the brands the authenticated user belongs to. Paginated — see [Pagination](/start/pagination/). ## Show [Section titled “Show”](#show) ```http GET /organizations/:id.json ``` Returns one brand. Sets an ETag — supply `If-None-Match` for `304 Not Modified`. Returns `404` if the brand exists but you’re not a member. ## Create [Section titled “Create”](#create) ```http POST /organizations.json { "organization": { "name": "Hot new brand", "privacy_setting": "public" } } ``` Requires a write-scoped token. The authenticated user becomes the brand’s owner. Returns `201 Created` with the new brand. Logo upload requires a multipart request. ## Update [Section titled “Update”](#update) ```http PATCH /organizations/:id.json { "organization": { "name": "Renamed", "website": "https://new.example.com" } } ``` Requires write scope and an admin role on the brand. Pass `purge_logo: "1"` to remove an existing logo. ## Delete [Section titled “Delete”](#delete) ```http DELETE /organizations/:id.json ``` Returns `204 No Content`. Fails with `422` if the brand has an active subscription. ## Errors [Section titled “Errors”](#errors) | Code | When | | ----- | ----------------------------------------------------- | | `401` | Missing token, or read token attempting a write | | `403` | Authenticated, but role does not permit this action | | `404` | Brand does not exist *for you* | | `422` | Validation failed (e.g. private brand without a logo) | # Social accounts > Connected social profiles (TikTok, YouTube, Twitter, etc.) belonging to the authenticated user. Connected social profiles (TikTok, YouTube, Twitter, etc.) belonging to the authenticated user. ## Resource shape [Section titled “Resource shape”](#resource-shape) ```json { "id": 17, "platform_id": "tiktok", "account_url": "https://tiktok.com/@example", "uid": "1234567890", "status": "verified", "subscriber_count": 12345, "view_count": 9876543, "video_count": 42, "likes_count": 100000, "engagement_rate": "5.2", "last_synced_at": "2026-05-05T07:55:00Z", "created_at": "2026-04-01T10:00:00Z", "updated_at": "2026-05-05T07:55:00Z", "url": "https://hypemarket.ai/me/social_accounts/17.json" } ``` `status` is one of `pending`, `verified`, `failed`. Metric fields (`subscriber_count` etc.) read from the latest snapshot and may be `null` for newly connected accounts that haven’t been synced yet. ## List [Section titled “List”](#list) ```http GET /me/social_accounts.json ``` Returns an array of social accounts belonging to the authenticated user. Paginated — see response headers `Total-Count`, `Total-Pages`. ## Show [Section titled “Show”](#show) ```http GET /me/social_accounts/:id.json ``` Returns one. Sets an ETag — supply `If-None-Match` for `304 Not Modified`. ## Create [Section titled “Create”](#create) ```http POST /me/social_accounts.json { "social_account": { "platform_id": "twitter", "account_url": "https://x.com/example" } } ``` Requires a write-scoped token. Returns `201 Created` with the new resource. OAuth platforms OAuth-based platforms (TikTok, YouTube) cannot be connected this way — they go through the browser OAuth flow. ## Delete [Section titled “Delete”](#delete) ```http DELETE /me/social_accounts/:id.json ``` Requires a write-scoped token. Returns `204 No Content`. ## Errors [Section titled “Errors”](#errors) | Code | When | | ----- | ------------------------------------------------------- | | `401` | Missing token, or read token attempting `POST`/`DELETE` | | `404` | Account does not exist or doesn’t belong to you | | `422` | Validation failed (e.g. duplicate `account_url`) | # Authentication > Create, use, and revoke personal access tokens (PATs) for the Hypemarket API. Tokens are user-bound and scoped read-only or read+write. The Hypemarket API uses **personal access tokens** (PATs). A token is bound to a single user; the same token works across every organization that user belongs to. ## Creating a token (web UI) [Section titled “Creating a token (web UI)”](#creating-a-token-web-ui) 1. Sign in at [hypemarket.ai](https://hypemarket.ai) 2. Navigate to **Account → API access tokens** (or visit [`/me/access_tokens`](https://hypemarket.ai/me/access_tokens)) 3. Click **New token**, give it a description (e.g. “My laptop script”) and choose a permission: * **Read-only** — `GET` and `HEAD` requests only * **Read and write** — all verbs One-time view The token is shown **once**. Copy it immediately — you cannot retrieve it again. Lost a token? Revoke it and create a new one. ## Creating a token (API) [Section titled “Creating a token (API)”](#creating-a-token-api) You can also mint tokens programmatically once you have any existing token: ```http POST /me/access_tokens.json Authorization: Bearer...
" } ``` `brief`-style rich-text fields are returned as pre-rendered HTML and are typically only included on `show`, not on `index`. ## Error responses [Section titled “Error responses”](#error-responses) For authorization / authentication errors: ```json { "error": "Not authorized" } ``` For validation errors (`422 Unprocessable Content`): ```json { "errors": { "name": ["can't be blank"] } } ``` The `errors` object is keyed by attribute name; each value is an array of human-readable messages. ## Content-Type [Section titled “Content-Type”](#content-type) Every JSON request **must** include: ```plaintext Accept: application/json ``` Mutation requests (`POST`, `PATCH`, `PUT`) should also send: ```plaintext Content-Type: application/json ``` Without `Accept: application/json`, endpoints respond with HTML — the same controllers serve both. ## See also [Section titled “See also”](#see-also) * [Pagination](/start/pagination/) * [ETags](/start/etags/) * [Errors](/start/errors/)