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 organization’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 organization. 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 an organization's brief that creators can apply to. Organization-scoped — the URL identifies the organization. A collab is an organization’s brief that creators can apply to. Org-scoped: the URL identifies the organization. ## Operations [Section titled “Operations”](#operations) | Operation | Method + path | Token scope | Role | Notes | | ------------- | --------------------------------------------------------- | ----------------- | ------------------- | ----------------------------------------------------- | | List collabs | `GET /organizations/:organization_id/collabs.json` | `read` or `write` | Organization member | Paginated | | Show collab | `GET /organizations/:organization_id/collabs/:id.json` | `read` or `write` | Organization member | ETag on `show` | | Create collab | `POST /organizations/:organization_id/collabs.json` | `write` | Organization admin | Creates a draft | | Update collab | `PATCH /organizations/:organization_id/collabs/:id.json` | `write` | Organization admin | `purge_banner_image` removes banner | | Delete collab | `DELETE /organizations/:organization_id/collabs/:id.json` | `write` | Organization admin | Only draft collabs without submissions can be deleted | Not exposed in JSON State transitions such as `submit`, `pause`, and `unpause` still redirect through HTML endpoints today. ## Resource shape [Section titled “Resource shape”](#resource-shape) ```json { "id": "qZmRpL", "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/gKpMxN/collabs/qZmRpL.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 organization’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 organization. You can send a `collab` payload to override the server-created draft defaults. Any omitted fields keep the generated defaults (for example the default name, default countries, default brief template, and the database default currency). 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, include `"purge_banner_image": "1"` inside the `collab` payload. ## Delete [Section titled “Delete”](#delete) ```http DELETE /organizations/:organization_id/collabs/:id.json ``` Returns `204 No Content` only for draft collabs with no submissions. Fails with `403` if the collab is no longer a draft, and `422` if any submissions exist. ## 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 an organization. Used to manage who's on the team and what role they hold. Organization-scoped. The link between a user and an organization. Org-scoped. Used to manage who’s on the team and what role they hold. ## Operations [Section titled “Operations”](#operations) | Operation | Method + path | Token scope | Role | Notes | | ----------------------------------- | --------------------------------------------------------- | ----------------- | ---------------------------------------- | ---------------------------------- | | List members | `GET /organizations/:organization_id/members.json` | `read` or `write` | Organization member | Paginated, admins first | | Change member role | `PATCH /organizations/:organization_id/members/:id.json` | `write` | Organization admin | Owner and last-admin guards apply | | Remove member or leave organization | `DELETE /organizations/:organization_id/members/:id.json` | `write` | Organization admin or the current member | Owner and last-member guards apply | ## Resource shape [Section titled “Resource shape”](#resource-shape) ```json { "id": "dHaBjN", "role": "admin", "is_owner": true, "created_at": "2026-04-01T10:00:00Z", "updated_at": "2026-04-01T10:00:00Z", "user": { "id": "nFsKwR", "name": "Yaro", "email": "yaro@example.com" } } ``` `role` is `member` or `admin`. `is_owner` is true for the organization owner — the owner cannot be removed or demoted. ## List [Section titled “List”](#list) ```http GET /organizations/:organization_id/members.json ``` Returns members of the organization, 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 organization. Cannot demote the only remaining admin. Cannot demote the organization 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 organization. Cannot remove: * The organization 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 organization 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. ## Operations [Section titled “Operations”](#operations) | Operation | Method + path | Token scope | Role | Notes | | ---------------------------- | -------------------------------------- | ----------------- | ------------------ | ----------------------------------------------- | | Show notification settings | `GET /me/notification_settings.json` | `read` or `write` | Authenticated user | Returns the current push preference state | | Update notification settings | `PATCH /me/notification_settings.json` | `write` | Authenticated user | Toggles delivery without removing subscriptions | ## 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. ## Operations [Section titled “Operations”](#operations) | Operation | Method + path | Token scope | Role | Notes | | ------------------ | ---------------------------- | ----------------- | ------------------ | ----------------------- | | List notifications | `GET /me/notifications.json` | `read` or `write` | Authenticated user | Paginated, newest first | Not exposed in JSON Marking notifications as seen or read is still UI-specific. The JSON endpoint is read-only. ## Resource shape [Section titled “Resource shape”](#resource-shape) ```json { "id": "pXmKbT", "type": "Membership::JoinRequestReceivedNotifier", "params": { "user_name": "Yaro", "organization_name": "Acme" }, "record_type": "Membership::JoinRequest", "record_id": "kRpMnX", "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 > An organization the authenticated user belongs to. Endpoints to list, show, create, update, and delete organizations. An organization the authenticated user belongs to. ## Operations [Section titled “Operations”](#operations) | Operation | Method + path | Token scope | Role | Notes | | ------------------- | -------------------------------- | ----------------- | ------------------- | ------------------------------------------- | | List organizations | `GET /organizations.json` | `read` or `write` | Authenticated user | Paginated | | Show organization | `GET /organizations/:id.json` | `read` or `write` | Organization member | ETag on `show` | | Create organization | `POST /organizations.json` | `write` | Authenticated user | Creator becomes owner | | Update organization | `PATCH /organizations/:id.json` | `write` | Organization admin | `purge_logo` removes logo | | Delete organization | `DELETE /organizations/:id.json` | `write` | Organization owner | Guarded by subscription and resource checks | ## Resource shape [Section titled “Resource shape”](#resource-shape) ```json { "id": "gKpMxN", "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/gKpMxN.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 organizations the authenticated user belongs to. Paginated — see [Pagination](/start/pagination/). ## Show [Section titled “Show”](#show) ```http GET /organizations/:id.json ``` Returns one organization. Sets an ETag — supply `If-None-Match` for `304 Not Modified`. Returns `404` if the organization exists but you’re not a member. ## Create [Section titled “Create”](#create) ```http POST /organizations.json { "organization": { "name": "Hot new organization", "privacy_setting": "public" } } ``` Requires a write-scoped token. The authenticated user becomes the organization’s owner. Returns `201 Created` with the new organization. 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 organization. To remove an existing logo, include `"purge_logo": "1"` inside the `organization` payload. ## Delete [Section titled “Delete”](#delete) ```http DELETE /organizations/:id.json ``` Returns `204 No Content`. Fails with `422` if the organization still has an active subscription, any campaigns, or any collabs. ## 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` | Organization does not exist *for you* | | `422` | Validation failed, or a delete guard blocked the operation | # 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. ## Operations [Section titled “Operations”](#operations) | Operation | Method + path | Token scope | Role | Notes | | --------------------- | ------------------------------------- | ----------------- | ------------------ | -------------------------------- | | List social accounts | `GET /me/social_accounts.json` | `read` or `write` | Authenticated user | Paginated | | Show social account | `GET /me/social_accounts/:id.json` | `read` or `write` | Authenticated user | ETag on `show` | | Create social account | `POST /me/social_accounts.json` | `write` | Authenticated user | Manual URL-based connection only | | Delete social account | `DELETE /me/social_accounts/:id.json` | `write` | Authenticated user | Returns `204 No Content` | Not exposed in JSON OAuth-based platform connection flows such as TikTok and YouTube still go through the browser OAuth flow. ## Resource shape [Section titled “Resource shape”](#resource-shape) ```json { "id": "vBcZpQ", "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/vBcZpQ.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 already have a **write-scoped** token: ```http POST /me/access_tokens.json Authorization: Bearer...
" } ``` `id` values are opaque strings (sqids), not integers — treat them as tokens. `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) Validation errors (`422 Unprocessable Content`) use a structured JSON envelope: ```json { "errors": { "name": ["can't be blank"] } } ``` The `errors` object is keyed by attribute name; each value is an array of human-readable messages. Authorization and missing-resource responses are less uniform: * Bearer-token failures (`401 Unauthorized`) may be header-only or plain text rather than JSON. * Organization-scoped `403 Forbidden` responses, and many organization-scoped `404 Not Found` responses, use: ```json { "error": "Not authorized" } ``` * Some user-scoped missing-resource responses return `404` with no body. Example: `GET /me/address.json` before the user has saved an address. ## Content-Type [Section titled “Content-Type”](#content-type) Use either of these to select JSON: * Request a `.json` URL, for example `/organizations.json` * Send `Accept: application/json` Using both is recommended, but either one is enough. If you send a JSON request body on `POST`, `PATCH`, or `PUT`, also send: ```plaintext Content-Type: application/json ``` Without a `.json` suffix or `Accept: application/json`, the same controllers fall back to HTML behavior. ## See also [Section titled “See also”](#see-also) * [Pagination](/start/pagination/) * [ETags](/start/etags/) * [Errors](/start/errors/)