Developers

API reference

Every endpoint of API v1, generated from the OpenAPI specification.

Endpoints 72
Account6
  1. GET Get the token owner
  2. GET Get your account
  3. PUT Go online or offline
  4. GET List breaks
  5. POST Start a break
  6. DELETE End the current break
Catalog3
  1. GET List games
  2. GET List a game’s categories
  3. GET Get a category’s attributes
Gift cards2
  1. GET List gift card brands
  2. GET List gift card regions
Listings11
  1. GET List your listings
  2. POST Create a listing
  3. PATCH Update many listings
  4. GET Get a listing
  5. PATCH Update a listing
  6. DELETE Delete a listing
  7. POST Pause a listing
  8. POST Activate a listing
  9. POST Duplicate a listing
  10. POST Update listings by filter
  11. GET List competing offers
Listing import3
  1. GET Download the CSV template
  2. POST Preview a CSV import
  3. POST Confirm a CSV import
Listing images4
  1. GET List a listing’s images
  2. POST Upload images
  3. PUT Reorder images
  4. DELETE Delete an image
Instant delivery units5
  1. GET List delivery units
  2. POST Add delivery units
  3. PATCH Edit one delivery unit
  4. DELETE Remove delivery units
  5. DELETE Remove one delivery unit
Orders8
  1. GET List orders
  2. GET Get an order
  3. POST Start an order
  4. POST Deliver an order
  5. POST Cancel and refund an order
  6. PATCH Correct the delivery
  7. GET Get the invoice
  8. GET Open the printable invoice
Order messages2
  1. GET List order messages
  2. POST Send an order message
Disputes8
  1. GET List disputes
  2. GET Get a dispute
  3. GET List dispute events
  4. GET Download an evidence file
  5. POST Accept the buyer’s request
  6. POST Make a counter-offer
  7. POST Escalate to MythicDeals
  8. POST Send a dispute message
Wallet2
  1. GET Get balances
  2. GET List ledger entries
Payouts2
  1. GET List payouts
  2. GET Get a payout
Notifications2
  1. GET List notifications
  2. POST Mark notifications as read
Boosting6
  1. GET List open boosting requests
  2. GET Get a boosting request
  3. GET List your boosting offers
  4. POST Send or update an offer
  5. POST Withdraw an offer
  6. POST Post boost progress
Webhooks8
  1. GET List webhook endpoints
  2. POST Create a webhook endpoint
  3. GET Get a webhook endpoint
  4. PATCH Update a webhook endpoint
  5. DELETE Delete a webhook endpoint
  6. POST Send a test event
  7. GET List deliveries
  8. POST Retry a delivery

Base URL: https://mythicdeals.com/api/v1. Send your token in the Authorization: Bearer go_… header; every request and response is JSON.

The examples read the token from the MYTHICDEALS_TOKEN environment variable. Errors, pagination, rate limits and idempotency work the same everywhere — see the overview.

Account

The token owner, your account status and restrictions, online/offline presence and breaks (vacation mode).

Get the token owner

#
GET /api/v1/me
Any scope

Who owns this token, whether they are a verified seller, and the token’s scopes and expiry. Works with any scope — use it to test a new token.

Responses

200The token owner.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/me' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "id": 1,
    "name": "Budi",
    "is_seller": true,
    "store": {
      "name": "Budi Store",
      "slug": "budi-store"
    },
    "token": {
      "name": "Sync bot",
      "prefix": "go_8fK2xQaZ",
      "scopes": [
        "catalog:read",
        "listings:read",
        "listings:write",
        "orders:read",
        "orders:write",
        "messages:read",
        "messages:write",
        "wallet:read",
        "webhooks:write",
        "disputes:read",
        "disputes:write",
        "notifications:read",
        "account:read",
        "account:write"
      ],
      "expires_at": null
    }
  }
}

Get your account

#
GET /api/v1/account
account:read

Your account in one call: email and seller verification, two-factor, seller level and fee, store, presence and current break, and restrictions — whether you can sell and withdraw right now, with reasons (account_suspended, seller_not_verified, email_not_verified, tax_info_required, on_break). limits repeats the API limits (prices, units, images, bulk sizes, CSV rows, requests per minute) so your tool does not have to hard-code them.

Responses

200Your account.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/account' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "id": 1,
    "name": "Budi",
    "email": "[email protected]",
    "email_verified": true,
    "two_factor": {
      "enabled": false,
      "methods": []
    },
    "seller": {
      "verified": true,
      "verification_status": "approved",
      "level": {
        "name": "NEW",
        "fee_percent": 10
      }
    },
    "store": {
      "name": "Budi Store",
      "slug": "budi-store",
      "url": "http://localhost:8000/store/budi-store"
    },
    "presence": {
      "status": "online",
      "appear_offline": false,
      "shown_online": false,
      "last_seen_at": null
    },
    "break": {
      "active": false,
      "until": null,
      "message": null
    },
    "restrictions": {
      "can_sell": true,
      "can_withdraw": true,
      "suspended": false,
      "suspended_until": null,
      "tax_info_required": false,
      "tax_info_complete": false,
      "reasons": []
    },
    "limits": {
      "price_min_cents": 100,
      "price_max_cents": 5000000,
      "units_per_listing": 200,
      "images_per_listing": 8,
      "bulk_items": 100,
      "bulk_update_listings": 1000,
      "import_rows": 500,
      "requests_per_minute": 120
    }
  }
}

Go online or offline

#
PUT /api/v1/account/status
account:write Verified seller

offline = appear offline: buyers see you as offline even while you use the website or the API. online = normal: buyers see you online while you were active in the last few minutes (shown_online). This does not close your store or hide listings — start a break for that. Safe to repeat.

Requires a verified seller account with a verified email address.

Parameters

NameDescription
statusrequired string · body online or offline (appear offline). One of: online offline

Responses

200Your presence now.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X PUT 'https://mythicdeals.com/api/v1/account/status' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"status":"offline"}'

Example response

200 OK
{
  "data": {
    "status": "offline",
    "appear_offline": true,
    "shown_online": false,
    "last_seen_at": null
  }
}

List breaks

#
GET /api/v1/account/breaks
account:read

Your breaks (vacation mode), newest first, whether they were started on the website or with the API (source). Standard pagination (data, links, meta) like every other list; meta.on_break tells whether your store is closed right now.

Parameters

NameDescription
per_page integer · query Items per page, 1–100. Range: 1–100 · Default: 25
page integer · query Page number. Range: 1–… · Default: 1

Responses

200A page of breaks.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/account/breaks' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "id": 1,
      "active": true,
      "started_at": "2026-10-27T09:30:07Z",
      "until": "2026-11-03T08:00:00Z",
      "ended_at": null,
      "message": "Back on November 3 — orders resume then.",
      "source": "api"
    }
  ],
  "links": {
    "first": "http://localhost:8000/api/v1/account/breaks?page=1",
    "last": "http://localhost:8000/api/v1/account/breaks?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "« Previous",
        "page": null,
        "active": false
      },
      {
        "url": "http://localhost:8000/api/v1/account/breaks?page=1",
        "label": "1",
        "page": 1,
        "active": true
      },
      {
        "url": null,
        "label": "Next »",
        "page": null,
        "active": false
      }
    ],
    "path": "http://localhost:8000/api/v1/account/breaks",
    "per_page": 25,
    "to": 1,
    "total": 1,
    "on_break": true
  }
}

Start a break

#
POST /api/v1/account/breaks
account:write Verified seller Idempotency-Key

Closes your store now (the “Store is closed” switch of the website): your listings are hidden and new purchases are refused. Orders already placed are not affected — keep delivering them. With until (in the future, less than a year away) the store reopens by itself; without it the break lasts until you end it. message is shown to buyers on your store. Already on a break → 409.

Requires a verified seller account with a verified email address. Accepts an Idempotency-Key header: retrying with the same key returns the first response.

Parameters

NameDescription
Idempotency-Key string · header Any unique string (e.g. a UUID), max 255 characters. For 24 hours the same key on the same endpoint returns the stored response (header Idempotent-Replayed: true). Same key with a different body → 409 idempotency_conflict. Length: 0–255
until date-time | null · body When the store reopens by itself (ISO-8601). Empty = until you end the break.
message string | null · body Note for buyers, shown on your store. Length: 0–280

Responses

201The break that just started.
400Bad request, e.g. invalid_idempotency_key (key longer than 255 characters).
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/account/breaks' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"until":"2026-11-03T08:00:00Z","message":"Back on November 3 — orders resume then."}'

Example response

201 Created
{
  "data": {
    "id": 1,
    "active": true,
    "started_at": "2026-10-27T09:30:07Z",
    "until": "2026-11-03T08:00:00Z",
    "ended_at": null,
    "message": "Back on November 3 — orders resume then.",
    "source": "api"
  }
}

End the current break

#
DELETE /api/v1/account/breaks/current
account:write Verified seller

Reopens your store now. Not on a break → 409.

Requires a verified seller account with a verified email address.

Responses

200The break that just ended.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X DELETE 'https://mythicdeals.com/api/v1/account/breaks/current' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "id": 1,
    "active": false,
    "started_at": "2026-10-27T09:30:07Z",
    "until": "2026-11-03T08:00:00Z",
    "ended_at": "2026-10-27T10:30:07Z",
    "message": "Back on November 3 — orders resume then.",
    "source": "api"
  }
}

Catalog

Games, categories and the attributes each category needs. Use it to build valid listings.

List games

#
GET /api/v1/games
catalog:read

All active games, with the listing types sold in each one. Not paginated.

Responses

200Active games.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/games' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "id": 2,
      "slug": "mobile-legends",
      "name": "Mobile Legends",
      "icon_url": null,
      "types": [
        "account",
        "currency",
        "boosting"
      ],
      "categories_count": 3
    },
    {
      "id": 5,
      "slug": "free-fire",
      "name": "Free Fire",
      "icon_url": null,
      "types": [
        "account",
        "currency",
        "boosting"
      ],
      "categories_count": 3
    }
  ]
}

List a game’s categories

#
GET /api/v1/games/{slug}/categories
catalog:read

Active categories of a game. The category decides the listing type and which attributes a listing needs. Add include=attributes to embed each category’s attribute schema.

Parameters

NameDescription
slugrequired string · path Game slug, e.g. valorant.
include string · query Set to attributes to embed each category’s attributes. One of: attributes

Responses

200Categories of the game.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/games/valorant/categories?include=attributes' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "id": 1,
      "game_id": 1,
      "name": "Accounts",
      "slug": "accounts",
      "type": "account",
      "supports_instant_delivery": true,
      "supports_topup_delivery": false,
      "attributes": [
        {
          "key": "region",
          "label": "Region",
          "type": "select",
          "options": [
            "EU",
            "NA",
            "AP",
            "KR",
            "BR",
            "LATAM"
          ],
          "ordered": false,
          "required": true,
          "filterable": true,
          "min": null,
          "max": null,
          "unit": null,
          "show_on_card": true,
          "sort_order": 0
        },
        {
          "key": "rank",
          "label": "Current rank",
          "type": "select",
          "options": [
            "Iron",
            "Bronze",
            "Silver",
            "Gold",
            "Platinum",
            "Diamond",
            "Ascendant",
            "Immortal",
            "Radiant"
          ],
          "ordered": true,
          "required": true,
          "filterable": true,
          "min": null,
          "max": null,
          "unit": null,
          "show_on_card": true,
          "sort_order": 1
        }
      ]
    },
    {
      "id": 2,
      "game_id": 1,
      "name": "Boosting",
      "slug": "boosting",
      "type": "boosting",
      "supports_instant_delivery": false,
      "supports_topup_delivery": false,
      "attributes": [
        {
          "key": "region",
          "label": "Region",
          "type": "select",
          "options": [
            "EU",
            "NA",
            "AP",
            "KR"
          ],
          "ordered": false,
          "required": true,
          "filterable": true,
          "min": null,
          "max": null,
          "unit": null,
          "show_on_card": true,
          "sort_order": 0
        },
        {
          "key": "rank_from",
          "label": "Rank from",
          "type": "select",
          "options": [
            "Iron",
            "Bronze",
            "Silver",
            "Gold",
            "Platinum",
            "Diamond",
            "Ascendant",
            "Immortal"
          ],
          "ordered": true,
          "required": true,
          "filterable": true,
          "min": null,
          "max": null,
          "unit": null,
          "show_on_card": true,
          "sort_order": 1
        }
      ]
    }
  ],
  "game": {
    "id": 1,
    "slug": "valorant",
    "name": "Valorant"
  }
}

Get a category’s attributes

#
GET /api/v1/categories/{id}/attributes
catalog:read

The attribute schema of one category: send these keys in attributes when you create a listing. select values must be one of options; number values must be within min–max; boolean takes true/false.

Parameters

NameDescription
idrequired integer · path Category id.

Responses

200Attributes of the category.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/categories/1/attributes' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "key": "region",
      "label": "Region",
      "type": "select",
      "options": [
        "EU",
        "NA",
        "AP",
        "KR",
        "BR",
        "LATAM"
      ],
      "ordered": false,
      "required": true,
      "filterable": true,
      "min": null,
      "max": null,
      "unit": null,
      "show_on_card": true,
      "sort_order": 0
    },
    {
      "key": "rank",
      "label": "Current rank",
      "type": "select",
      "options": [
        "Iron",
        "Bronze",
        "Silver",
        "Gold",
        "Platinum",
        "Diamond",
        "Ascendant",
        "Immortal",
        "Radiant"
      ],
      "ordered": true,
      "required": true,
      "filterable": true,
      "min": null,
      "max": null,
      "unit": null,
      "show_on_card": true,
      "sort_order": 1
    },
    {
      "key": "agents_owned",
      "label": "Agents owned",
      "type": "number",
      "options": null,
      "ordered": false,
      "required": true,
      "filterable": true,
      "min": 0,
      "max": 30,
      "unit": null,
      "show_on_card": true,
      "sort_order": 2
    }
  ],
  "category": {
    "id": 1,
    "game_id": 1,
    "name": "Accounts",
    "slug": "accounts",
    "type": "account",
    "supports_instant_delivery": true,
    "supports_topup_delivery": false
  }
}

Gift cards

Gift card brands and regions. A gift card offer is a normal listing of type `giftcard`; its codes are its instant-delivery units.

List gift card brands

#
GET /api/v1/giftcards/brands
catalog:read

Brands that sell gift cards, with everything you need to create an offer: game_id + game_category_id for POST /listings, the accepted regions, face_currencies and face value range, plus how many offers are live and the lowest price. Filter with q (name or slug contains). Not paginated.

Parameters

NameDescription
q string · query Text the brand name or slug contains. Length: 0–100

Responses

200Gift card brands.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/giftcards/brands?q=steam' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "id": 9,
      "slug": "steam",
      "name": "Steam",
      "icon_url": null,
      "game_id": 9,
      "game_category_id": 21,
      "regions": [
        "Global",
        "US",
        "EU",
        "UK",
        "DE",
        "FR",
        "ID",
        "MY",
        "PH",
        "SG",
        "TH",
        "JP",
        "BR",
        "IN",
        "TR",
        "CA",
        "AU",
        "LATAM"
      ],
      "face_currencies": [
        "USD",
        "EUR",
        "GBP",
        "IDR",
        "MYR",
        "PHP",
        "SGD",
        "THB",
        "JPY",
        "BRL",
        "INR",
        "TRY",
        "CAD",
        "AUD"
      ],
      "face_value_min": 1,
      "face_value_max": 10000000,
      "offers_count": 0,
      "lowest_price_cents": null,
      "currency": "USD"
    }
  ]
}

List gift card regions

#
GET /api/v1/giftcards/regions
catalog:read

Every code accepted in the region attribute of a gift card listing, with its English name and whether it is a single country. meta.face_currencies lists the currencies accepted in face_currency.

Responses

200Regions.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/giftcards/regions' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "code": "Global",
      "name": "Global",
      "slug": "global",
      "is_country": false
    },
    {
      "code": "US",
      "name": "United States",
      "slug": "us",
      "is_country": true
    },
    {
      "code": "EU",
      "name": "Europe",
      "slug": "eu",
      "is_country": false
    },
    {
      "code": "UK",
      "name": "United Kingdom",
      "slug": "uk",
      "is_country": true
    },
    {
      "code": "DE",
      "name": "Germany",
      "slug": "de",
      "is_country": true
    },
    {
      "code": "FR",
      "name": "France",
      "slug": "fr",
      "is_country": true
    },
    {
      "code": "ID",
      "name": "Indonesia",
      "slug": "id",
      "is_country": true
    },
    {
      "code": "MY",
      "name": "Malaysia",
      "slug": "my",
      "is_country": true
    },
    {
      "code": "PH",
      "name": "Philippines",
      "slug": "ph",
      "is_country": true
    },
    {
      "code": "SG",
      "name": "Singapore",
      "slug": "sg",
      "is_country": true
    },
    {
      "code": "TH",
      "name": "Thailand",
      "slug": "th",
      "is_country": true
    },
    {
      "code": "JP",
      "name": "Japan",
      "slug": "jp",
      "is_country": true
    },
    {
      "code": "BR",
      "name": "Brazil",
      "slug": "br",
      "is_country": true
    },
    {
      "code": "IN",
      "name": "India",
      "slug": "in",
      "is_country": true
    },
    {
      "code": "TR",
      "name": "Turkey",
      "slug": "tr",
      "is_country": true
    },
    {
      "code": "CA",
      "name": "Canada",
      "slug": "ca",
      "is_country": true
    },
    {
      "code": "AU",
      "name": "Australia",
      "slug": "au",
      "is_country": true
    },
    {
      "code": "LATAM",
      "name": "Latin America",
      "slug": "latam",
      "is_country": false
    }
  ],
  "meta": {
    "face_currencies": [
      "USD",
      "EUR",
      "GBP",
      "IDR",
      "MYR",
      "PHP",
      "SGD",
      "THB",
      "JPY",
      "BRL",
      "INR",
      "TRY",
      "CAD",
      "AUD"
    ]
  }
}

Listings

Create, read, update, duplicate, pause and delete your own listings, one by one, in bulk or by filter, and compare them with other sellers’ offers.

List your listings

#
GET /api/v1/listings
listings:read

Your own listings, newest change first by default. Use updated_since to sync only what changed.

Parameters

NameDescription
status string · query Only listings with this status. One of: draft active paused sold_out removed
type string · query Only this listing type. One of: account currency item boosting giftcard
game string · query Game id or slug.
category integer · query Category id.
q string · query Text the title contains. Length: 0–100
updated_since date-time · query Only listings updated at or after this time (ISO-8601).
sort string · query Sort field; prefix with - for descending. price sorts by price_cents. One of: id created_at updated_at price stock title -id -created_at -updated_at -price -stock -title Default: -updated_at
per_page integer · query Items per page, 1–100. Range: 1–100 · Default: 25
page integer · query Page number. Range: 1–… · Default: 1

Responses

200A page of listings.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/listings?status=active&per_page=50' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "id": 1,
      "title": "Immortal 2 account, 42 skins",
      "description": null,
      "status": "active",
      "type": "account",
      "game": {
        "id": 1,
        "slug": "valorant",
        "name": "Valorant"
      },
      "category": {
        "id": 1,
        "slug": "accounts",
        "name": "Accounts"
      },
      "price_cents": 11999,
      "currency": "USD",
      "input_price": {
        "amount": "119.99",
        "currency": "USD"
      },
      "stock": 3,
      "min_quantity": 1,
      "delivery_eta_minutes": 30,
      "warranty_days": 7,
      "instant_delivery": {
        "enabled": false,
        "units": 0
      },
      "topup": null,
      "attributes": {
        "region": "EU",
        "rank": "Immortal",
        "agents_owned": 23,
        "skin_count": 42,
        "level": 212,
        "email_change": true
      },
      "images": [],
      "url": "http://localhost:8000/listing/1",
      "created_at": "2026-10-26T15:54:50Z",
      "updated_at": "2026-10-26T15:54:50Z"
    }
  ],
  "links": {
    "first": "http://localhost:8000/api/v1/listings?per_page=1&page=1",
    "last": "http://localhost:8000/api/v1/listings?per_page=1&page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "« Previous",
        "page": null,
        "active": false
      },
      {
        "url": "http://localhost:8000/api/v1/listings?per_page=1&page=1",
        "label": "1",
        "page": 1,
        "active": true
      },
      {
        "url": null,
        "label": "Next »",
        "page": null,
        "active": false
      }
    ],
    "path": "http://localhost:8000/api/v1/listings",
    "per_page": 1,
    "to": 1,
    "total": 1
  }
}

Create a listing

#
POST /api/v1/listings
listings:write Verified seller Idempotency-Key

Creates a listing with exactly the same rules as the website form. Send the price either as price_cents (USD cents) or as price + currency (converted to USD at the current rate). After conversion the price must be between $1.00 and $50,000.00. attributes are checked against the category schema (GET /categories/{id}/attributes).

Gift cards: use the game_id + game_category_id of a brand (GET /giftcards/brands), attributes region, face_value and face_currency, and the codes in delivery_units as {code, pin?, expires_at?}. Gift cards are always delivered instantly, one code per sale: stock is the number of codes (whatever you send), warranty is 0, and delivery_eta_minutes defaults to 5. Without codes a gift card can only be saved as a draft. Add more codes later with POST /listings/{id}/units.

Requires a verified seller account with a verified email address. Accepts an Idempotency-Key header: retrying with the same key returns the first response.

Parameters

NameDescription
Idempotency-Key string · header Any unique string (e.g. a UUID), max 255 characters. For 24 hours the same key on the same endpoint returns the stored response (header Idempotent-Replayed: true). Same key with a different body → 409 idempotency_conflict. Length: 0–255
game_idrequired integer · body Game id (GET /games).
game_category_idrequired integer · body Category id of that game. Decides the listing type.
titlerequired string · body Title, 10–160 characters. Length: 10–160
description string | null · body Description, up to 5000 characters. Length: 0–5000
status string · body Default draft. One of: draft active
price_cents integer · body Price in USD cents. Send this OR price + currency. Range: 100–5000000
price number | string · body Price as typed in currency (e.g. "119.99" or 166000). Converted to USD cents.
currency string · body Currency of price. One of: USD IDR EUR GBP PHP BRL INR MYR Default: USD
stock integer · body Quantity for sale. Required, except with auto_delivery (= number of units) and for gift cards (always = number of codes). Range: 0–9999
delivery_eta_minutes integer · body Promised delivery time in minutes (5 min – 14 days). Required, except for gift cards (default 5). Range: 5–20160
warranty_days integer · body Warranty in days. Always 0 for gift cards. One of: 0 3 7 30 Default: 0
attributes object · body Category attributes {key: value}. See GET /categories/{id}/attributes.
auto_delivery boolean · body Turn instant delivery on (account and item listings). Requires delivery_units. Gift cards are always instant; the flag is ignored for them.
delivery_units object[] · body Instant-delivery units; one unit = one item of stock. Accounts: username + password (+ email, note). Items: note. Gift cards: code (+ pin, expires_at YYYY-MM-DD) — at least one code unless the listing is a draft. Max items: 200
delivery_units[].username string · body Login (accounts). Length: 0–160
delivery_units[].password string · body Password (accounts). Length: 0–160
delivery_units[].email string · body Email of the account (optional). Length: 0–160
delivery_units[].note string · body Free text, e.g. a code or instructions. Length: 0–1000
delivery_units[].code string · body Gift card code (gift cards only, required for them). Length: 0–255
delivery_units[].pin string · body Gift card PIN, if any. Length: 0–64
delivery_units[].expires_at string · body Gift card expiry, YYYY-MM-DD, not in the past.
topup_provider string | null · body Top-up supplier for automatic delivery (currency categories only; connect it on the website first). One of: digiflazz
topup_sku string | null · body Supplier SKU. Required with topup_provider. Length: 0–80

Responses

201The new listing.
400Bad request, e.g. invalid_idempotency_key (key longer than 255 characters).
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/listings' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"game_id":1,"game_category_id":1,"status":"active","title":"Immortal 2 account, 42 skins","price_cents":11999,"stock":3,"delivery_eta_minutes":30,"warranty_days":7,"attributes":{"region":"EU","rank":"Immortal","agents_owned":23,"skin_count":42,"level":212,"email_change":true}}'

Example response

201 Created
{
  "data": {
    "id": 1,
    "title": "Immortal 2 account, 42 skins",
    "description": null,
    "status": "active",
    "type": "account",
    "game": {
      "id": 1,
      "slug": "valorant",
      "name": "Valorant"
    },
    "category": {
      "id": 1,
      "slug": "accounts",
      "name": "Accounts"
    },
    "price_cents": 11999,
    "currency": "USD",
    "input_price": {
      "amount": "119.99",
      "currency": "USD"
    },
    "stock": 3,
    "min_quantity": 1,
    "delivery_eta_minutes": 30,
    "warranty_days": 7,
    "instant_delivery": {
      "enabled": false,
      "units": 0
    },
    "topup": null,
    "attributes": {
      "region": "EU",
      "rank": "Immortal",
      "agents_owned": 23,
      "skin_count": 42,
      "level": 212,
      "email_change": true
    },
    "images": [],
    "url": "http://localhost:8000/listing/1",
    "created_at": "2026-10-26T15:54:50Z",
    "updated_at": "2026-10-26T15:54:50Z"
  }
}

Update many listings

#
PATCH /api/v1/listings/bulk
listings:write Verified seller

Changes price_cents, stock and/or status of up to 100 listings in one transaction. Each item gets its own result. With atomic: true, one failed item cancels everything (422 bulk_failed). Item error codes: not_found, duplicate_item, conflict (removed listing), validation_failed, stock_managed_by_units, cannot_activate (status: active on a listing that cannot be published yet — see POST /listings/{id}/activate; the message says why), rolled_back.

Requires a verified seller account with a verified email address.

Parameters

NameDescription
itemsrequired object[] · body Up to 100 changes; each needs id and at least one of price_cents, stock, status. Max items: 100
items[].idrequired integer · body
items[].price_cents integer · body Range: 100–5000000
items[].stock integer · body Range: 0–9999
items[].status string · body One of: draft active paused
atomic boolean · body true: save nothing if any item fails. Default: false

Responses

200Per-item results.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
422Validation failed, or bulk_failed when atomic and an item failed (body then also has data with per-item results).
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X PATCH 'https://mythicdeals.com/api/v1/listings/bulk' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"items":[{"id":1,"price_cents":9999,"stock":4},{"id":2,"status":"paused"}],"atomic":false}'

Example response

200 OK
{
  "data": [
    {
      "id": 1,
      "ok": true,
      "listing": {
        "id": 1,
        "status": "active",
        "price_cents": 9999,
        "currency": "USD",
        "stock": 4,
        "updated_at": "2026-10-26T15:54:50Z"
      }
    },
    {
      "id": 999999,
      "ok": false,
      "error": {
        "code": "not_found",
        "message": "Listing not found."
      }
    }
  ],
  "meta": {
    "total": 2,
    "updated": 1,
    "failed": 1
  }
}

Get a listing

#
GET /api/v1/listings/{id}
listings:read

One of your listings. Another seller’s listing returns 404.

Parameters

NameDescription
idrequired integer · path Listing id.

Responses

200The listing.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/listings/1' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "id": 1,
    "title": "Immortal 2 account, 42 skins",
    "description": null,
    "status": "active",
    "type": "account",
    "game": {
      "id": 1,
      "slug": "valorant",
      "name": "Valorant"
    },
    "category": {
      "id": 1,
      "slug": "accounts",
      "name": "Accounts"
    },
    "price_cents": 11999,
    "currency": "USD",
    "input_price": {
      "amount": "119.99",
      "currency": "USD"
    },
    "stock": 3,
    "min_quantity": 1,
    "delivery_eta_minutes": 30,
    "warranty_days": 7,
    "instant_delivery": {
      "enabled": false,
      "units": 0
    },
    "topup": null,
    "attributes": {
      "region": "EU",
      "rank": "Immortal",
      "agents_owned": 23,
      "skin_count": 42,
      "level": 212,
      "email_change": true
    },
    "images": [],
    "url": "http://localhost:8000/listing/1",
    "created_at": "2026-10-26T15:54:50Z",
    "updated_at": "2026-10-26T15:54:50Z"
  }
}

Update a listing

#
PATCH /api/v1/listings/{id}
listings:write Verified seller

Changes only the fields you send; the result is validated with the same rules as creating. attributes are merged with the current ones (replaced if you change the category). stock of a listing with instant-delivery units follows its units — use the units endpoints instead. delivery_units are only applied together with auto_delivery: true, and then REPLACE all units (stock = units − units reserved by orders not delivered yet); this is also how you replace the codes of a gift card in one call. A removed listing returns 409.

Requires a verified seller account with a verified email address.

Parameters

NameDescription
idrequired integer · path Listing id.
game_id integer · body Game id. If you send only game_category_id, the game is taken from the category.
game_category_id integer · body Category id of that game. Decides the listing type.
title string · body Title, 10–160 characters. Length: 10–160
description string | null · body Description, up to 5000 characters. Length: 0–5000
status string · body New status. One of: draft active paused
price_cents integer · body Price in USD cents. Send this OR price + currency. Range: 100–5000000
price number | string · body Price as typed in currency (e.g. "119.99" or 166000). Converted to USD cents.
currency string · body Currency of price. One of: USD IDR EUR GBP PHP BRL INR MYR Default: USD
stock integer · body Quantity for sale. Not for listings whose stock follows units (instant delivery, gift cards). Range: 0–9999
delivery_eta_minutes integer · body Promised delivery time in minutes (5 min – 14 days). Range: 5–20160
warranty_days integer · body Warranty in days. Always 0 for gift cards. One of: 0 3 7 30 Default: 0
attributes object · body Category attributes {key: value}. See GET /categories/{id}/attributes.
auto_delivery boolean · body true + delivery_units replaces all units; false turns instant delivery off and deletes the units. delivery_units are only read when auto_delivery is sent — for gift cards send auto_delivery: true with the new codes.
delivery_units object[] · body Instant-delivery units; one unit = one item of stock. Accounts: username + password (+ email, note). Items: note. Gift cards: code (+ pin, expires_at YYYY-MM-DD) — at least one code unless the listing is a draft. Max items: 200
delivery_units[].username string · body Login (accounts). Length: 0–160
delivery_units[].password string · body Password (accounts). Length: 0–160
delivery_units[].email string · body Email of the account (optional). Length: 0–160
delivery_units[].note string · body Free text, e.g. a code or instructions. Length: 0–1000
delivery_units[].code string · body Gift card code (gift cards only, required for them). Length: 0–255
delivery_units[].pin string · body Gift card PIN, if any. Length: 0–64
delivery_units[].expires_at string · body Gift card expiry, YYYY-MM-DD, not in the past.
topup_provider string | null · body Top-up supplier for automatic delivery (currency categories only; connect it on the website first). One of: digiflazz
topup_sku string | null · body Supplier SKU. Required with topup_provider. Length: 0–80

Responses

200The updated listing.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X PATCH 'https://mythicdeals.com/api/v1/listings/1' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"stock":5,"price_cents":10999}'

Example response

200 OK
{
  "data": {
    "id": 1,
    "title": "Immortal 2 account, 42 skins",
    "description": null,
    "status": "active",
    "type": "account",
    "game": {
      "id": 1,
      "slug": "valorant",
      "name": "Valorant"
    },
    "category": {
      "id": 1,
      "slug": "accounts",
      "name": "Accounts"
    },
    "price_cents": 10999,
    "currency": "USD",
    "input_price": {
      "amount": "109.99",
      "currency": "USD"
    },
    "stock": 5,
    "min_quantity": 1,
    "delivery_eta_minutes": 30,
    "warranty_days": 7,
    "instant_delivery": {
      "enabled": false,
      "units": 0
    },
    "topup": null,
    "attributes": {
      "region": "EU",
      "rank": "Immortal",
      "agents_owned": 23,
      "skin_count": 42,
      "level": 212,
      "email_change": true
    },
    "images": [],
    "url": "http://localhost:8000/listing/1",
    "created_at": "2026-10-26T15:54:50Z",
    "updated_at": "2026-10-26T15:54:50Z"
  }
}

Delete a listing

#
DELETE /api/v1/listings/{id}
listings:write Verified seller

A listing that was never ordered is deleted. A listing with orders is marked removed instead (hidden from the store, order history kept) and can no longer be changed.

Requires a verified seller account with a verified email address.

Parameters

NameDescription
idrequired integer · path Listing id.

Responses

200Deletion result.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X DELETE 'https://mythicdeals.com/api/v1/listings/1' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "id": 1,
    "deleted": false,
    "status": "removed"
  }
}

Pause a listing

#
POST /api/v1/listings/{id}/pause
listings:write Verified seller

Sets the status to paused (hidden from buyers). Safe to repeat.

Requires a verified seller account with a verified email address.

Parameters

NameDescription
idrequired integer · path Listing id.

Responses

200The paused listing.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/listings/1/pause' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "id": 1,
    "title": "Immortal 2 account, 42 skins",
    "description": null,
    "status": "paused",
    "type": "account",
    "game": {
      "id": 1,
      "slug": "valorant",
      "name": "Valorant"
    },
    "category": {
      "id": 1,
      "slug": "accounts",
      "name": "Accounts"
    },
    "price_cents": 10999,
    "currency": "USD",
    "input_price": {
      "amount": "109.99",
      "currency": "USD"
    },
    "stock": 5,
    "min_quantity": 1,
    "delivery_eta_minutes": 30,
    "warranty_days": 7,
    "instant_delivery": {
      "enabled": false,
      "units": 0
    },
    "topup": null,
    "attributes": {
      "region": "EU",
      "rank": "Immortal",
      "agents_owned": 23,
      "skin_count": 42,
      "level": 212,
      "email_change": true
    },
    "images": [],
    "url": "http://localhost:8000/listing/1",
    "created_at": "2026-10-26T15:54:50Z",
    "updated_at": "2026-10-26T15:54:50Z"
  }
}

Activate a listing

#
POST /api/v1/listings/{id}/activate
listings:write Verified seller

Sets the status to active (visible to buyers). Safe to repeat. The same publish rules as the website apply to a listing that is not active yet: stock above 0, at least one code for a gift card, and every required attribute of its category filled. Otherwise → 409 cannot_activate with the reason in message. The same rules apply to status: active in PATCH /listings/bulk and POST /listings/bulk-update.

Requires a verified seller account with a verified email address.

Parameters

NameDescription
idrequired integer · path Listing id.

Responses

200The active listing.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/listings/1/activate' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "id": 1,
    "title": "Immortal 2 account, 42 skins",
    "description": null,
    "status": "active",
    "type": "account",
    "game": {
      "id": 1,
      "slug": "valorant",
      "name": "Valorant"
    },
    "category": {
      "id": 1,
      "slug": "accounts",
      "name": "Accounts"
    },
    "price_cents": 10999,
    "currency": "USD",
    "input_price": {
      "amount": "109.99",
      "currency": "USD"
    },
    "stock": 5,
    "min_quantity": 1,
    "delivery_eta_minutes": 30,
    "warranty_days": 7,
    "instant_delivery": {
      "enabled": false,
      "units": 0
    },
    "topup": null,
    "attributes": {
      "region": "EU",
      "rank": "Immortal",
      "agents_owned": 23,
      "skin_count": 42,
      "level": 212,
      "email_change": true
    },
    "images": [],
    "url": "http://localhost:8000/listing/1",
    "created_at": "2026-10-26T15:54:50Z",
    "updated_at": "2026-10-26T15:54:50Z"
  }
}

Duplicate a listing

#
POST /api/v1/listings/{id}/duplicate
listings:write Verified seller Idempotency-Key

Creates a copy as a draft: same game, category, title, description, price, attributes, delivery time, warranty and top-up settings, with copies of the photos. Instant-delivery units are NOT copied (an account or a code can only be sold once): the copy of an instant-delivery listing starts with stock 0 and instant delivery off. Copies of sold_out or removed listings also start with stock 0. meta.duplicated_from is the source listing.

Requires a verified seller account with a verified email address. Accepts an Idempotency-Key header: retrying with the same key returns the first response.

Parameters

NameDescription
idrequired integer · path Listing id.
Idempotency-Key string · header Any unique string (e.g. a UUID), max 255 characters. For 24 hours the same key on the same endpoint returns the stored response (header Idempotent-Replayed: true). Same key with a different body → 409 idempotency_conflict. Length: 0–255

Responses

201The new draft.
400Bad request, e.g. invalid_idempotency_key (key longer than 255 characters).
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/listings/1/duplicate' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: $(uuidgen)"

Example response

201 Created
{
  "data": {
    "id": 3,
    "title": "Immortal 2 account, 42 skins",
    "description": null,
    "status": "draft",
    "type": "account",
    "game": {
      "id": 1,
      "slug": "valorant",
      "name": "Valorant"
    },
    "category": {
      "id": 1,
      "slug": "accounts",
      "name": "Accounts"
    },
    "price_cents": 11999,
    "currency": "USD",
    "input_price": {
      "amount": "119.99",
      "currency": "USD"
    },
    "stock": 3,
    "min_quantity": 1,
    "delivery_eta_minutes": 30,
    "warranty_days": 7,
    "instant_delivery": {
      "enabled": false,
      "units": 0
    },
    "topup": null,
    "attributes": {
      "region": "EU",
      "rank": "Immortal",
      "agents_owned": 23,
      "skin_count": 42,
      "level": 212,
      "email_change": true
    },
    "images": [],
    "url": "http://localhost:8000/listing/3",
    "created_at": "2026-10-27T10:30:35Z",
    "updated_at": "2026-10-27T10:30:35Z"
  },
  "meta": {
    "duplicated_from": 1
  }
}

Update listings by filter

#
POST /api/v1/listings/bulk-update
listings:write Verified seller

Changes every listing that matches filter, in one transaction — e.g. “all my active Valorant listings −5 %”. Filters (at least one, combined): game (id or slug), type, category (id), status (one or a list, not removed) and ids. Removed listings never match. Changes (at least one): price with exactly one of set_cents, percent (−90 to 500) or delta_cents; stock.set; status.set; delivery_eta_minutes.

New prices are rounded to whole cents and kept between $1.00 and $50,000.00: a listing whose price had to be clamped gets a price_clamped note (a set_cents outside that range is refused with 422 instead). The stock of instant-delivery listings and gift cards follows their units and is never changed (stock_managed_by_units note). status.set: active follows the publish rules of POST /listings/{id}/activate (stock above 0 after this change, codes for gift cards, required attributes filled): a listing that does not pass keeps its status and gets a cannot_activate note with the reason; its other changes still apply. Changed prices are stored in USD (input_price becomes the USD amount).

dry_run: true returns exactly the same before / after for each listing without saving anything — run it first. At most 1000 listings per call: more matches → 422 too_many_matches; narrow the filter.

Requires a verified seller account with a verified email address.

Parameters

NameDescription
filterrequired object · body Which listings: at least one filter, all must match.
changerequired object · body What to change: at least one.
dry_run boolean · body true: show the plan, save nothing. Default: false

Responses

200The plan (dry run) or what was changed.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
422Validation failed, or too_many_matches (with max) when more listings match than one call may change.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/listings/bulk-update' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"filter":{"game":"valorant","status":"active"},"change":{"price":{"percent":-5},"stock":{"set":10}},"dry_run":true}'

Example response

200 OK
{
  "data": [
    {
      "id": 1,
      "title": "Immortal 2 account, 42 skins",
      "changed": true,
      "before": {
        "price_cents": 11999,
        "stock": 3,
        "status": "active",
        "delivery_eta_minutes": 30
      },
      "after": {
        "price_cents": 11399,
        "stock": 10,
        "status": "active",
        "delivery_eta_minutes": 30
      },
      "notes": []
    },
    {
      "id": 2,
      "title": "Diamond 3 account, 18 skins",
      "changed": true,
      "before": {
        "price_cents": 4500,
        "stock": 2,
        "status": "active",
        "delivery_eta_minutes": 30
      },
      "after": {
        "price_cents": 4275,
        "stock": 2,
        "status": "active",
        "delivery_eta_minutes": 30
      },
      "notes": [
        {
          "field": "stock",
          "code": "stock_managed_by_units",
          "message": "Stock of an instant-delivery listing follows its units; not changed."
        }
      ]
    }
  ],
  "meta": {
    "dry_run": true,
    "matched": 2,
    "changed": 2,
    "unchanged": 0,
    "max": 1000
  }
}

List competing offers

#
GET /api/v1/listings/{id}/competitors
listings:read

Offers from OTHER sellers for the same thing as one of your listings, cheapest first, with your position. “The same thing” = same game, type and category, and the same value for the key attributes your listing has (region, server, platform; for currency listings also product, item_type, amount, amount_m) — see meta.matched_on. Only offers a buyer can buy right now count: active, in stock, seller not on a break or suspended. Your own listings are never included.

meta.your_rank (1 = cheapest) and meta.lowest_price_cents use your current price. The competitor list itself is cached for 60 seconds per listing (up to 100 offers); limit only shortens the response. Only public information is returned — the same as on listing and store pages.

Parameters

NameDescription
idrequired integer · path Listing id.
limit integer · query How many offers to return. Range: 1–100 · Default: 20

Responses

200Competing offers and your rank.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/listings/1/competitors' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "listing_id": 4,
      "title": "Immortal 1 EU account, full access",
      "price_cents": 10999,
      "currency": "USD",
      "stock": 2,
      "delivery_eta_minutes": 15,
      "instant_delivery": false,
      "warranty_days": 3,
      "url": "http://localhost:8000/listing/4",
      "seller": {
        "store_name": "Arif Games",
        "store_slug": "arif-games",
        "store_url": "http://localhost:8000/store/arif-games",
        "rating": null,
        "reviews": 0,
        "completed_orders": 0,
        "online": false
      }
    },
    {
      "listing_id": 5,
      "title": "Radiant EU account, 120 skins, OG",
      "price_cents": 24900,
      "currency": "USD",
      "stock": 1,
      "delivery_eta_minutes": 60,
      "instant_delivery": false,
      "warranty_days": 14,
      "url": "http://localhost:8000/listing/5",
      "seller": {
        "store_name": "Arif Games",
        "store_slug": "arif-games",
        "store_url": "http://localhost:8000/store/arif-games",
        "rating": null,
        "reviews": 0,
        "completed_orders": 0,
        "online": false
      }
    }
  ],
  "meta": {
    "listing_id": 1,
    "your_price_cents": 11999,
    "currency": "USD",
    "your_rank": 2,
    "competitors": 2,
    "lowest_price_cents": 10999,
    "matched_on": {
      "game_id": 1,
      "type": "account",
      "category_id": 1,
      "attributes": {
        "region": "EU"
      }
    },
    "cached_for_seconds": 60
  }
}

Listing import

Create many listings at once from a CSV file, in two steps: preview, then confirm.

Download the CSV template

#
GET /api/v1/listings/import/template
listings:read

A CSV file for one category (category = category id): a header row with the base columns title, description, price, currency, stock, delivery_minutes, warranty_days, status followed by the category’s attribute keys, and one example row starting with # (rows starting with # are skipped on import). currency sets the currency of the example price (default: your account currency). The column list is also sent in the X-Import-Columns header. Gift card categories cannot be imported by CSV (they need codes): asking for their template returns 422 on category, like the preview.

Parameters

NameDescription
categoryrequired integer · query Category id.
currency string · query Currency of the example price. One of: USD IDR EUR GBP PHP BRL INR MYR

Responses

200The CSV template (text/csv).
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/listings/import/template?category=1' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -o 'template.csv'

Example response

200 OK · text/csv
title,description,price,currency,stock,delivery_minutes,warranty_days,status,region,rank,agents_owned,skin_count,level,email_change,region_locked
"# Example: Valorant accounts (delete this row)","What the buyer gets, in a sentence or two",9.99,USD,1,30,0,active,EU,Iron,0,0,1,yes,yes

Preview a CSV import

#
POST /api/v1/listings/import/preview
listings:write Verified seller

Step 1 of 2. Upload the filled-in CSV (multipart: category and file; .csv or .txt, at most 2 MB, comma- or semicolon-separated, one category per file, at most 500 rows). The columns title, price and stock are required. Nothing is saved: every row is checked with the same rules as the website form; valid rows come back in rows, the others in errors with their line number. If at least one row is valid you get a token, valid 30 minutes and only for your account, to confirm the import. Gift card categories cannot be imported (422 — they need codes; use POST /listings).

Requires a verified seller account with a verified email address.

Parameters

NameDescription
categoryrequired integer · body · multipart Category id of every row.
filerequired file · body · multipart The CSV file (.csv or .txt, max 2 MB).

Responses

200Checked rows, errors and the confirmation token.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/listings/import/preview' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -F 'category=1' \
  -F '[email protected]'

Example response

200 OK
{
  "data": {
    "token": "ZNOq8GLdBWfObEHZSDTWRd3pw4vvBN6r",
    "expires_at": "2026-10-27T11:00:42Z",
    "category": {
      "id": 1,
      "slug": "accounts",
      "name": "Accounts",
      "game": {
        "id": 1,
        "slug": "valorant",
        "name": "Valorant"
      }
    },
    "total": 3,
    "valid": 2,
    "invalid": 1,
    "rows": [
      {
        "line": 2,
        "title": "Immortal 3 account EU, 40 skins",
        "price_cents": 12000,
        "currency": "USD",
        "input_price": {
          "amount": "120",
          "currency": "USD"
        },
        "stock": 1,
        "delivery_eta_minutes": 30,
        "warranty_days": 7,
        "status": "active"
      },
      {
        "line": 4,
        "title": "Diamond 2 account EU, 12 skins",
        "price_cents": 4550,
        "currency": "USD",
        "input_price": {
          "amount": "45.5",
          "currency": "USD"
        },
        "stock": 1,
        "delivery_eta_minutes": 30,
        "warranty_days": 7,
        "status": "active"
      }
    ],
    "errors": [
      {
        "line": 3,
        "messages": [
          "The title field must be at least 10 characters."
        ]
      }
    ]
  }
}

Confirm a CSV import

#
POST /api/v1/listings/import/confirm
listings:write Verified seller Idempotency-Key

Step 2 of 2. Creates the valid rows of a preview. A token works once: used, expired or belonging to another account → 409 preview_expired (upload the file again).

Requires a verified seller account with a verified email address. Accepts an Idempotency-Key header: retrying with the same key returns the first response.

Parameters

NameDescription
Idempotency-Key string · header Any unique string (e.g. a UUID), max 255 characters. For 24 hours the same key on the same endpoint returns the stored response (header Idempotent-Replayed: true). Same key with a different body → 409 idempotency_conflict. Length: 0–255
tokenrequired string · body token from the preview. Length: 0–64

Responses

201The new listings.
400Bad request, e.g. invalid_idempotency_key (key longer than 255 characters).
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/listings/import/confirm' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"token":"wCuxHYgC8H1AzVoTxCioBGN9hGVwBHG5"}'

Example response

201 Created
{
  "data": {
    "imported": 2,
    "listing_ids": [
      6,
      7
    ]
  }
}

Listing images

Photos of a listing. The first image is the cover.

List a listing’s images

#
GET /api/v1/listings/{id}/images
listings:read

Images in display order; the first one is the cover.

Parameters

NameDescription
idrequired integer · path Listing id.

Responses

200The images.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/listings/1/images' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "id": 2,
      "url": "http://localhost:8000/storage/listings/1/9ku6x84XJkln4LqpWjX4rumxWai9zUeB.webp",
      "thumb_url": "http://localhost:8000/storage/listings/1/9ku6x84XJkln4LqpWjX4rumxWai9zUeB.webp",
      "width": 40,
      "height": 40,
      "position": 0
    },
    {
      "id": 1,
      "url": "http://localhost:8000/storage/listings/1/H6UsGnCLtB0acYwjwiGBiRKK6ZEy7a6D.webp",
      "thumb_url": "http://localhost:8000/storage/listings/1/H6UsGnCLtB0acYwjwiGBiRKK6ZEy7a6D.webp",
      "width": 40,
      "height": 40,
      "position": 1
    }
  ],
  "meta": {
    "max_images": 8,
    "max_kb": 2048
  }
}

Upload images

#
POST /api/v1/listings/{id}/images
listings:write Verified seller Idempotency-Key

Multipart upload of one or more files in photos[] (a single photos file also works). JPG, PNG or WebP, up to 8 images per listing, each at most meta.max_kb KB (5 MB, or less if the server’s upload limit is lower). Images are resized and metadata (EXIF) is removed. New images are added after the existing ones.

Requires a verified seller account with a verified email address. Accepts an Idempotency-Key header: retrying with the same key returns the first response.

Parameters

NameDescription
idrequired integer · path Listing id.
Idempotency-Key string · header Any unique string (e.g. a UUID), max 255 characters. For 24 hours the same key on the same endpoint returns the stored response (header Idempotent-Replayed: true). Same key with a different body → 409 idempotency_conflict. Length: 0–255
photos[]required file[] · body · multipart Image files (JPG, PNG, WebP). Max items: 8

Responses

201All images of the listing.
400Bad request, e.g. invalid_idempotency_key (key longer than 255 characters).
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/listings/1/images' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -F 'photos[][email protected]'

Example response

201 Created
{
  "data": [
    {
      "id": 1,
      "url": "http://localhost:8000/storage/listings/1/H6UsGnCLtB0acYwjwiGBiRKK6ZEy7a6D.webp",
      "thumb_url": "http://localhost:8000/storage/listings/1/H6UsGnCLtB0acYwjwiGBiRKK6ZEy7a6D.webp",
      "width": 40,
      "height": 40,
      "position": 0
    },
    {
      "id": 2,
      "url": "http://localhost:8000/storage/listings/1/9ku6x84XJkln4LqpWjX4rumxWai9zUeB.webp",
      "thumb_url": "http://localhost:8000/storage/listings/1/9ku6x84XJkln4LqpWjX4rumxWai9zUeB.webp",
      "width": 40,
      "height": 40,
      "position": 1
    }
  ],
  "meta": {
    "max_images": 8,
    "max_kb": 2048
  }
}

Reorder images

#
PUT /api/v1/listings/{id}/images/order
listings:write Verified seller

Send image ids in the order you want. The first becomes the cover.

Requires a verified seller account with a verified email address.

Parameters

NameDescription
idrequired integer · path Listing id.
idsrequired integer[] · body Image ids of this listing, no duplicates. Unknown ids → 422. Max items: 8

Responses

200The images in their new order.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X PUT 'https://mythicdeals.com/api/v1/listings/1/images/order' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"ids":[2,1]}'

Example response

200 OK
{
  "data": [
    {
      "id": 2,
      "url": "http://localhost:8000/storage/listings/1/9ku6x84XJkln4LqpWjX4rumxWai9zUeB.webp",
      "thumb_url": "http://localhost:8000/storage/listings/1/9ku6x84XJkln4LqpWjX4rumxWai9zUeB.webp",
      "width": 40,
      "height": 40,
      "position": 0
    },
    {
      "id": 1,
      "url": "http://localhost:8000/storage/listings/1/H6UsGnCLtB0acYwjwiGBiRKK6ZEy7a6D.webp",
      "thumb_url": "http://localhost:8000/storage/listings/1/H6UsGnCLtB0acYwjwiGBiRKK6ZEy7a6D.webp",
      "width": 40,
      "height": 40,
      "position": 1
    }
  ],
  "meta": {
    "max_images": 8,
    "max_kb": 2048
  }
}

Delete an image

#
DELETE /api/v1/listings/{id}/images/{imageId}
listings:write Verified seller

Deletes one image and returns the remaining ones.

Requires a verified seller account with a verified email address.

Parameters

NameDescription
idrequired integer · path Listing id.
imageIdrequired integer · path Image id.

Responses

200The remaining images.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X DELETE 'https://mythicdeals.com/api/v1/listings/1/images/2' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "id": 2,
      "url": "http://localhost:8000/storage/listings/1/9ku6x84XJkln4LqpWjX4rumxWai9zUeB.webp",
      "thumb_url": "http://localhost:8000/storage/listings/1/9ku6x84XJkln4LqpWjX4rumxWai9zUeB.webp",
      "width": 40,
      "height": 40,
      "position": 0
    }
  ],
  "meta": {
    "max_images": 8,
    "max_kb": 2048
  }
}

Instant delivery units

Accounts or codes delivered automatically the moment an order is paid. One unit = one item of stock.

List delivery units

#
GET /api/v1/listings/{id}/units
listings:read

Units are stored encrypted and never returned in full: you get a stable id and a masked preview (passwords always ••••••). meta.reserved = units held by orders that are not delivered yet.

Parameters

NameDescription
idrequired integer · path Listing id.

Responses

200The units.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/listings/1/units' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "id": "bc137614c70229ef",
      "preview": {
        "username": "ga•••ne",
        "password": "••••••",
        "email": "ga•••[email protected]"
      }
    },
    {
      "id": "89a8a8a11863054a",
      "preview": {
        "username": "pl•••wo",
        "password": "••••••"
      }
    }
  ],
  "meta": {
    "listing_id": 1,
    "instant_delivery": true,
    "count": 2,
    "reserved": 0,
    "stock": 2,
    "max_units": 200
  }
}

Add delivery units

#
POST /api/v1/listings/{id}/units
listings:write Verified seller Idempotency-Key

Adds units and turns instant delivery on. Only for account and item listings. Account units need username and password; item units keep only note (e.g. a code). Identical units are skipped (meta.skipped_duplicates). At most 200 units per listing. Stock is recalculated: units − reserved. A listing delivered by a top-up supplier returns 409.

Requires a verified seller account with a verified email address. Accepts an Idempotency-Key header: retrying with the same key returns the first response.

Parameters

NameDescription
idrequired integer · path Listing id.
Idempotency-Key string · header Any unique string (e.g. a UUID), max 255 characters. For 24 hours the same key on the same endpoint returns the stored response (header Idempotent-Replayed: true). Same key with a different body → 409 idempotency_conflict. Length: 0–255
unitsrequired object[] · body Units to add.
units[].username string · body Login (accounts). Length: 0–160
units[].password string · body Password (accounts). Length: 0–160
units[].email string · body Email of the account (optional). Length: 0–160
units[].note string · body Free text, e.g. a code or instructions. Length: 0–1000
units[].code string · body Gift card code (gift cards only, required for them). Length: 0–255
units[].pin string · body Gift card PIN, if any. Length: 0–64
units[].expires_at string · body Gift card expiry, YYYY-MM-DD, not in the past.

Responses

201All units, with `added` and `skipped_duplicates` in meta.
400Bad request, e.g. invalid_idempotency_key (key longer than 255 characters).
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/listings/1/units' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"units":[{"username":"gamer_one","password":"hunter22","email":"[email protected]"},{"username":"player_two","password":"p4ssw0rd"}]}'

Example response

201 Created
{
  "data": [
    {
      "id": "bc137614c70229ef",
      "preview": {
        "username": "ga•••ne",
        "password": "••••••",
        "email": "ga•••[email protected]"
      }
    },
    {
      "id": "89a8a8a11863054a",
      "preview": {
        "username": "pl•••wo",
        "password": "••••••"
      }
    }
  ],
  "meta": {
    "listing_id": 1,
    "instant_delivery": true,
    "count": 2,
    "reserved": 0,
    "stock": 2,
    "max_units": 200,
    "added": 2,
    "skipped_duplicates": 0
  }
}

Edit one delivery unit

#
PATCH /api/v1/listings/{id}/units/{unitId}
listings:write Verified seller

Changes the fields you send of one unit and keeps the others: username, password, email and note for account listings, note for item listings, code, pin and expires_at for gift cards (same rules as adding: expires_at is YYYY-MM-DD and not in the past). null or "" clears an optional field. A field that does not apply to the listing’s type → 422 on that field (it is never silently ignored). A unit’s id is derived from its content, so it changes: the response has the full list plus meta.unit with previous_id, the new id and the masked preview (codes, PINs and passwords are never returned in clear). Same content as another unit of the listing, or a gift card code another unit already has (case-insensitive) → 409; a unit left empty or a gift card without code → 422 (delete it instead).

Requires a verified seller account with a verified email address.

Parameters

NameDescription
idrequired integer · path Listing id.
unitIdrequired string · path Unit id from GET /listings/{id}/units (16 hex characters).
username string · body Login (accounts). Length: 0–160
password string · body Password (accounts). Length: 0–160
email string · body Email of the account (optional). Length: 0–160
note string · body Free text, e.g. a code or instructions. Length: 0–1000
code string · body Gift card code (gift cards only, required for them). Length: 0–255
pin string · body Gift card PIN, if any. Length: 0–64
expires_at string · body Gift card expiry, YYYY-MM-DD, not in the past.

Responses

200All units, with the edited one in meta.unit.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X PATCH 'https://mythicdeals.com/api/v1/listings/1/units/bc137614c70229ef' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"password":"n3w-p4ss","email":"[email protected]"}'

Example response

200 OK
{
  "data": [
    {
      "id": "bc137614c70229ef",
      "preview": {
        "username": "ga•••ne",
        "password": "••••••",
        "email": "ga•••[email protected]"
      }
    },
    {
      "id": "46be555ac7272e57",
      "preview": {
        "username": "pl•••wo",
        "password": "••••••",
        "email": "pl•••[email protected]"
      }
    }
  ],
  "meta": {
    "listing_id": 2,
    "instant_delivery": true,
    "count": 2,
    "reserved": 0,
    "stock": 2,
    "max_units": 200,
    "unit": {
      "previous_id": "89a8a8a11863054a",
      "id": "46be555ac7272e57",
      "preview": {
        "username": "pl•••wo",
        "password": "••••••",
        "email": "pl•••[email protected]"
      }
    }
  }
}

Remove delivery units

#
DELETE /api/v1/listings/{id}/units
listings:write Verified seller

Removes the units in ids, or all of them with {"all": true}. You must keep at least as many units as are reserved by pending orders (409 otherwise). Removing every unit turns instant delivery off.

Requires a verified seller account with a verified email address.

Parameters

NameDescription
idrequired integer · path Listing id.
ids string[] · body Unit ids to remove (required unless all). Max items: 200
all boolean · body true to remove every unit.

Responses

200The remaining units.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X DELETE 'https://mythicdeals.com/api/v1/listings/1/units' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"ids":["bc137614c70229ef"]}'

Example response

200 OK
{
  "data": [],
  "meta": {
    "listing_id": 1,
    "instant_delivery": false,
    "count": 0,
    "reserved": 0,
    "stock": 0,
    "max_units": 200
  }
}

Remove one delivery unit

#
DELETE /api/v1/listings/{id}/units/{unitId}
listings:write Verified seller

Removes one unit by id. Same reservation rule as the bulk removal.

Requires a verified seller account with a verified email address.

Parameters

NameDescription
idrequired integer · path Listing id.
unitIdrequired string · path Unit id from GET /listings/{id}/units (16 hex characters).

Responses

200The remaining units.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X DELETE 'https://mythicdeals.com/api/v1/listings/1/units/bc137614c70229ef' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "id": "89a8a8a11863054a",
      "preview": {
        "username": "pl•••wo",
        "password": "••••••"
      }
    }
  ],
  "meta": {
    "listing_id": 1,
    "instant_delivery": true,
    "count": 1,
    "reserved": 0,
    "stock": 1,
    "max_units": 200
  }
}

Orders

Your sales (and, read-only, your purchases). Start, deliver, correct, cancel and invoice orders.

List orders

#
GET /api/v1/orders
orders:read

Your sales by default; role=buyer lists your purchases. Seller view includes buyer, buyer_note and topup_fields; buyer view includes seller. Lists never include delivered credentials.

Parameters

NameDescription
role string · query Whose side: your sales (seller) or your purchases (buyer). One of: seller buyer Default: seller
status string · query One status or several separated by commas: pending_payment, paid, processing, delivered, completed, disputed, refunded, expired, cancelled.
created_since date-time · query Only orders created at or after this time.
updated_since date-time · query Only orders updated at or after this time.
sort string · query Sort order; - = descending. One of: created_at -created_at updated_at -updated_at Default: -created_at
per_page integer · query Items per page, 1–100. Range: 1–100 · Default: 25
page integer · query Page number. Range: 1–… · Default: 1

Responses

200A page of orders.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/orders?status=paid%2Cprocessing' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "id": 1,
      "number": "48291735",
      "status": "paid",
      "listing": {
        "id": 1,
        "title": "Immortal 2 account, 42 skins",
        "type": "account",
        "game": "Valorant"
      },
      "quantity": 1,
      "unit_price_cents": 9999,
      "subtotal_cents": 9999,
      "buyer_fee_cents": 0,
      "discount_cents": 0,
      "total_paid_cents": 9999,
      "platform_fee_cents": 999,
      "fee_percent": 10,
      "seller_amount_cents": 9000,
      "currency": "USD",
      "buyer": {
        "id": 2,
        "name": "Rina"
      },
      "buyer_note": null,
      "topup_fields": null,
      "delivery": null,
      "dispute": null,
      "payment_due_at": "2026-10-26T16:54:50Z",
      "paid_at": "2026-10-26T15:54:50Z",
      "delivery_due_at": "2026-10-26T16:24:50Z",
      "delivered_at": null,
      "auto_release_at": null,
      "completed_at": null,
      "warranty_ends_at": null,
      "created_at": "2026-10-26T15:54:50Z",
      "updated_at": "2026-10-26T15:54:50Z"
    }
  ],
  "links": {
    "first": "http://localhost:8000/api/v1/orders?status=paid&page=1",
    "last": "http://localhost:8000/api/v1/orders?status=paid&page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "« Previous",
        "page": null,
        "active": false
      },
      {
        "url": "http://localhost:8000/api/v1/orders?status=paid&page=1",
        "label": "1",
        "page": 1,
        "active": true
      },
      {
        "url": null,
        "label": "Next »",
        "page": null,
        "active": false
      }
    ],
    "path": "http://localhost:8000/api/v1/orders",
    "per_page": 25,
    "to": 1,
    "total": 1
  }
}

Get an order

#
GET /api/v1/orders/{order}
orders:read

One order where you are the seller or the buyer. As the buyer, delivery.credentials contains what the seller delivered.

Parameters

NameDescription
orderrequired string · path Order id, or the 8-digit order number shown as #48291735 (the # is optional).

Responses

200The order.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/orders/48291735' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "id": 1,
    "number": "48291735",
    "status": "paid",
    "listing": {
      "id": 1,
      "title": "Immortal 2 account, 42 skins",
      "type": "account",
      "game": "Valorant"
    },
    "quantity": 1,
    "unit_price_cents": 9999,
    "subtotal_cents": 9999,
    "buyer_fee_cents": 0,
    "discount_cents": 0,
    "total_paid_cents": 9999,
    "platform_fee_cents": 999,
    "fee_percent": 10,
    "seller_amount_cents": 9000,
    "currency": "USD",
    "buyer": {
      "id": 2,
      "name": "Rina"
    },
    "buyer_note": null,
    "topup_fields": null,
    "delivery": null,
    "dispute": null,
    "payment_due_at": "2026-10-26T16:54:50Z",
    "paid_at": "2026-10-26T15:54:50Z",
    "delivery_due_at": "2026-10-26T16:24:50Z",
    "delivered_at": null,
    "auto_release_at": null,
    "completed_at": null,
    "warranty_ends_at": null,
    "created_at": "2026-10-26T15:54:50Z",
    "updated_at": "2026-10-26T15:54:50Z"
  }
}

Start an order

#
POST /api/v1/orders/{order}/start
orders:write Verified seller

Marks a paid order as processing (you are working on it). Calling it again on a processing order just returns the order. Other statuses return 409.

Requires a verified seller account with a verified email address.

Parameters

NameDescription
orderrequired string · path Order id, or the 8-digit order number shown as #48291735 (the # is optional).

Responses

200The order.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/orders/48291735/start' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "id": 1,
    "number": "48291735",
    "status": "processing",
    "listing": {
      "id": 1,
      "title": "Immortal 2 account, 42 skins",
      "type": "account",
      "game": "Valorant"
    },
    "quantity": 1,
    "unit_price_cents": 9999,
    "subtotal_cents": 9999,
    "buyer_fee_cents": 0,
    "discount_cents": 0,
    "total_paid_cents": 9999,
    "platform_fee_cents": 999,
    "fee_percent": 10,
    "seller_amount_cents": 9000,
    "currency": "USD",
    "buyer": {
      "id": 2,
      "name": "Rina"
    },
    "buyer_note": null,
    "topup_fields": null,
    "delivery": null,
    "dispute": null,
    "payment_due_at": "2026-10-26T16:54:50Z",
    "paid_at": "2026-10-26T15:54:50Z",
    "delivery_due_at": "2026-10-26T16:24:50Z",
    "delivered_at": null,
    "auto_release_at": null,
    "completed_at": null,
    "warranty_ends_at": null,
    "created_at": "2026-10-26T15:54:50Z",
    "updated_at": "2026-10-26T15:54:50Z"
  }
}

Deliver an order

#
POST /api/v1/orders/{order}/deliver
orders:write Verified seller Idempotency-Key

Delivers a paid or processing order: credentials and/or a note go to the buyer (stored encrypted), plus optional proof screenshots (send multipart for those). A paid order is started automatically in the same transaction (two events, both by you: paid → processing → delivered), so calling POST /orders/{order}/start first is optional. An order held for a risk check cannot be delivered yet → 409. The buyer then has until auto_release_at to confirm or open a dispute. If the order is already delivered, nothing is delivered twice and meta.already_delivered is true. To fix details after delivery, use PATCH /orders/{order}/delivery.

Requires a verified seller account with a verified email address. Accepts an Idempotency-Key header: retrying with the same key returns the first response.

Parameters

NameDescription
orderrequired string · path Order id, or the 8-digit order number shown as #48291735 (the # is optional).
Idempotency-Key string · header Any unique string (e.g. a UUID), max 255 characters. For 24 hours the same key on the same endpoint returns the stored response (header Idempotent-Replayed: true). Same key with a different body → 409 idempotency_conflict. Length: 0–255
username string · body Login (accounts). Length: 0–160
password string · body Password (accounts). Length: 0–160
email string · body Email of the account (optional). Length: 0–160
note string · body Free text, e.g. a code or instructions. Length: 0–1000
proofs[] file[] · body · multipart Proof screenshots: JPG, PNG or WebP, max 5 files, 4 MB each. Max items: 5

Responses

200The delivered order.
400Bad request, e.g. invalid_idempotency_key (key longer than 255 characters).
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/orders/48291735/deliver' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"username":"gamer_one","password":"hunter22","note":"Change the password after login."}'

Example response

200 OK
{
  "data": {
    "id": 1,
    "number": "48291735",
    "status": "delivered",
    "listing": {
      "id": 1,
      "title": "Immortal 2 account, 42 skins",
      "type": "account",
      "game": "Valorant"
    },
    "quantity": 1,
    "unit_price_cents": 9999,
    "subtotal_cents": 9999,
    "buyer_fee_cents": 0,
    "discount_cents": 0,
    "total_paid_cents": 9999,
    "platform_fee_cents": 999,
    "fee_percent": 10,
    "seller_amount_cents": 9000,
    "currency": "USD",
    "buyer": {
      "id": 2,
      "name": "Rina"
    },
    "buyer_note": null,
    "topup_fields": null,
    "delivery": {
      "delivered_at": "2026-10-26T15:54:50Z",
      "has_credentials": true,
      "proof_count": 0
    },
    "dispute": null,
    "payment_due_at": "2026-10-26T16:54:50Z",
    "paid_at": "2026-10-26T15:54:50Z",
    "delivery_due_at": "2026-10-26T16:24:50Z",
    "delivered_at": "2026-10-26T15:54:50Z",
    "auto_release_at": "2026-10-29T15:54:50Z",
    "completed_at": null,
    "warranty_ends_at": null,
    "created_at": "2026-10-26T15:54:50Z",
    "updated_at": "2026-10-26T15:54:50Z"
  },
  "meta": {
    "already_delivered": false
  }
}

Cancel and refund an order

#
POST /api/v1/orders/{order}/cancel
orders:write Verified seller Idempotency-Key

Cancels a paid or processing order that has not been delivered, with a full refund to the buyer through escrow: the order becomes refunded. reason (5–500 characters) is shown to the buyer. restock: true puts the quantity back into the listing’s stock (default false — useful when you cancel because the stock was wrong). Delivered, unpaid or finished orders, and orders whose automatic top-up is already running, return 409.

Requires a verified seller account with a verified email address. Accepts an Idempotency-Key header: retrying with the same key returns the first response.

Parameters

NameDescription
orderrequired string · path Order id, or the 8-digit order number shown as #48291735 (the # is optional).
Idempotency-Key string · header Any unique string (e.g. a UUID), max 255 characters. For 24 hours the same key on the same endpoint returns the stored response (header Idempotent-Replayed: true). Same key with a different body → 409 idempotency_conflict. Length: 0–255
reasonrequired string · body Why you cancel; the buyer sees it. Length: 5–500
restock boolean · body Put the quantity back into stock. Default: false

Responses

200The refunded order.
400Bad request, e.g. invalid_idempotency_key (key longer than 255 characters).
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/orders/48291735/cancel' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"reason":"Out of stock, sorry — refunded in full.","restock":true}'

Example response

200 OK
{
  "data": {
    "id": 1,
    "number": "48293969",
    "status": "refunded",
    "listing": {
      "id": 1,
      "title": "Immortal 2 account, 42 skins",
      "type": "account",
      "game": "Valorant"
    },
    "quantity": 1,
    "unit_price_cents": 11999,
    "subtotal_cents": 11999,
    "buyer_fee_cents": 0,
    "discount_cents": 0,
    "total_paid_cents": 11999,
    "platform_fee_cents": 1199,
    "fee_percent": 10,
    "seller_amount_cents": 10800,
    "currency": "USD",
    "buyer": {
      "id": 2,
      "name": "Rina"
    },
    "buyer_note": null,
    "topup_fields": null,
    "delivery": null,
    "dispute": null,
    "payment_due_at": "2026-10-27T11:31:56Z",
    "paid_at": "2026-10-27T10:31:56Z",
    "delivery_due_at": "2026-10-27T11:01:56Z",
    "delivered_at": null,
    "auto_release_at": null,
    "completed_at": null,
    "warranty_ends_at": null,
    "created_at": "2026-10-27T10:31:56Z",
    "updated_at": "2026-10-27T10:33:56Z"
  }
}

Correct the delivery

#
PATCH /api/v1/orders/{order}/delivery
orders:write Verified seller

Replaces the delivered details while the order is delivered, disputed, or completed and still under warranty. Send reason (5–500 characters, shown to the buyer) and the fields that change — fields you leave out keep their previous value; at least one field or one proof is required. Proof screenshots go in proofs[] (multipart; if your client cannot send a multipart PATCH, send a POST with _method=PATCH).

The previous delivery is kept as history (meta.deliveries, newest last), the buyer is notified and sees the new details, and auto_release_at starts again. Not delivered yet, or past the warranty → 409.

Requires a verified seller account with a verified email address.

Parameters

NameDescription
orderrequired string · path Order id, or the 8-digit order number shown as #48291735 (the # is optional).
reasonrequired string · body What you corrected; the buyer sees it. Length: 5–500
username string · body Login (accounts). Length: 0–160
password string · body Password (accounts). Length: 0–160
email string · body Email of the account (optional). Length: 0–160
note string · body Free text, e.g. a code or instructions. Length: 0–1000
proofs[] file[] · body · multipart Proof screenshots: JPG, PNG or WebP, max 5 files, 4 MB each. Max items: 5

Responses

200The order, with the delivery history in meta.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X PATCH 'https://mythicdeals.com/api/v1/orders/48291735/delivery' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"password":"hunter23","reason":"The password had a typo — fixed."}'

Example response

200 OK
{
  "data": {
    "id": 2,
    "number": "48295086",
    "status": "delivered",
    "listing": {
      "id": 1,
      "title": "Immortal 2 account, 42 skins",
      "type": "account",
      "game": "Valorant"
    },
    "quantity": 1,
    "unit_price_cents": 11999,
    "subtotal_cents": 11999,
    "buyer_fee_cents": 0,
    "discount_cents": 0,
    "total_paid_cents": 11999,
    "platform_fee_cents": 1199,
    "fee_percent": 10,
    "seller_amount_cents": 10800,
    "currency": "USD",
    "buyer": {
      "id": 2,
      "name": "Rina"
    },
    "buyer_note": null,
    "topup_fields": null,
    "delivery": {
      "delivered_at": "2026-10-27T11:09:56Z",
      "has_credentials": true,
      "proof_count": 0
    },
    "dispute": null,
    "payment_due_at": "2026-10-27T11:34:56Z",
    "paid_at": "2026-10-27T10:34:56Z",
    "delivery_due_at": "2026-10-27T11:04:56Z",
    "delivered_at": "2026-10-27T10:39:56Z",
    "auto_release_at": "2026-10-30T11:09:56Z",
    "completed_at": null,
    "warranty_ends_at": null,
    "created_at": "2026-10-27T10:34:56Z",
    "updated_at": "2026-10-27T11:09:56Z"
  },
  "meta": {
    "delivery_id": 2,
    "deliveries": [
      {
        "id": 1,
        "delivered_at": "2026-10-27T10:39:56Z",
        "amends_delivery_id": null,
        "reason": null,
        "has_credentials": true
      },
      {
        "id": 2,
        "delivered_at": "2026-10-27T11:09:56Z",
        "amends_delivery_id": 1,
        "reason": "The password had a typo — fixed.",
        "has_credentials": true
      }
    ]
  }
}

Get the invoice

#
GET /api/v1/orders/{order}/invoice
orders:read

The invoice of a paid order, for its buyer or its seller: lines, buyer fee, discount, taxes, refunds and total, in USD cents. The seller also gets seller_summary (platform fee and what you receive). html_url is a printable HTML version that opens without a token: a signed link valid for 24 hours (html_url_expires_at). An order that was never paid has no invoice → 409.

Parameters

NameDescription
orderrequired string · path Order id, or the 8-digit order number shown as #48291735 (the # is optional).

Responses

200The invoice.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/orders/48291735/invoice' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "invoice_number": "48293969",
    "order": {
      "id": 1,
      "number": "48293969",
      "status": "paid"
    },
    "issued_at": "2026-10-27T10:31:56Z",
    "currency": "USD",
    "issuer": {
      "name": "MythicDeals",
      "role": "marketplace",
      "note": "Payment collected by MythicDeals on behalf of the seller."
    },
    "seller": {
      "id": 1,
      "store_name": "Budi Store"
    },
    "buyer": {
      "id": 2,
      "name": "Rina"
    },
    "lines": [
      {
        "description": "Immortal 2 account, 42 skins",
        "game": "Valorant",
        "type": "account",
        "quantity": 1,
        "unit_price_cents": 11999,
        "amount_cents": 11999
      }
    ],
    "subtotal_cents": 11999,
    "buyer_fee_cents": 0,
    "discount_cents": 0,
    "coupon_code": null,
    "tax_lines": [],
    "tax_cents": 0,
    "total_cents": 11999,
    "refunded_cents": 0,
    "payment_method": null,
    "seller_summary": {
      "platform_fee_cents": 1199,
      "fee_percent": 10,
      "seller_discount_cents": 0,
      "seller_amount_cents": 10800
    },
    "html_url": "http://localhost:8000/api/v1/orders/1/invoice.html?expires=1793183636&viewer=seller&signature=9303ba180af5232dbc57e8ba077fb34e1955ec272ba84ab9d1c7852a556d2b50",
    "html_url_expires_at": "2026-10-28T10:33:56Z"
  }
}

Open the printable invoice

#
GET /api/v1/orders/{order}/invoice.html
No token — signed link

The invoice as a printable HTML page. Do not build this URL yourself: open html_url from GET /orders/{order}/invoice. It needs no token — open it in a browser or send it to a printer — and is valid for 24 hours. It shows the view of whoever requested the link (viewer: the seller view includes what you receive). A changed or expired link → 403 forbidden. Limited to 60 requests per minute.

Parameters

NameDescription
orderrequired integer · path Order id (number only).
expiresrequired integer · query Expiry (Unix time), part of the signed link.
viewerrequired string · query Whose view, part of the signed link. One of: buyer seller
signaturerequired string · query Signature of the link.

Responses

200The printable invoice (text/html).
403forbidden: the signature is invalid or the link expired. Get a new html_url.
404not_found: it does not exist or belongs to someone else.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/orders/1/invoice.html?expires=1793183636&viewer=seller&signature=9303ba180af5232dbc57e8ba077fb34e1955ec272ba84ab9d1c7852a556d2b50' \
  -o 'invoice.html'

Example response

200 OK · text/html
<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="robots" content="noindex">
    <title>Invoice 48293969 · MythicDeals</title>
    <style>…</style>
</head>
<body>
  …
</body>
</html>

Order messages

The chat of one order, between its buyer and its seller.

List order messages

#
GET /api/v1/orders/{order}/messages
messages:read

Messages oldest first, with a cursor: pass the last id you have as since_id and keep calling with meta.next_since_id while meta.has_more is true. Reading does NOT mark messages as read unless mark_read=1.

Parameters

NameDescription
orderrequired string · path Order id, or the 8-digit order number shown as #48291735 (the # is optional).
since_id integer · query Return messages with an id greater than this. Range: 0–… · Default: 0
per_page integer · query Items per page, 1–100. Range: 1–100 · Default: 25
mark_read boolean · query Also mark the other party’s messages as read. Default: false

Responses

200Messages after since_id.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/orders/48291735/messages?since_id=0' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "id": 1,
      "order_id": 1,
      "sender": {
        "id": null,
        "name": "MythicDeals",
        "role": "system"
      },
      "body": "Payment received",
      "is_system": true,
      "attachments": [],
      "read_at": "2026-10-26T15:54:50Z",
      "created_at": "2026-10-26T15:54:50Z"
    }
  ],
  "meta": {
    "per_page": 1,
    "has_more": true,
    "next_since_id": 1
  }
}

Send an order message

#
POST /api/v1/orders/{order}/messages
messages:write Idempotency-Key

Sends a message as the buyer or seller of the order. Text, files (multipart) or both. The chat opens once the order is paid (409 chat_closed before that, and for expired or cancelled orders).

Accepts an Idempotency-Key header: retrying with the same key returns the first response.

Parameters

NameDescription
orderrequired string · path Order id, or the 8-digit order number shown as #48291735 (the # is optional).
Idempotency-Key string · header Any unique string (e.g. a UUID), max 255 characters. For 24 hours the same key on the same endpoint returns the stored response (header Idempotent-Replayed: true). Same key with a different body → 409 idempotency_conflict. Length: 0–255
body string · body Message text. Required unless you send files. Length: 0–2000
files[] file[] · body · multipart JPG, PNG, WebP or PDF, max 5 files, 4 MB each. Max items: 5

Responses

201The new message.
400Bad request, e.g. invalid_idempotency_key (key longer than 255 characters).
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/orders/48291735/messages' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"body":"Hello, delivering now."}'

Example response

201 Created
{
  "data": {
    "id": 4,
    "order_id": 1,
    "sender": {
      "id": 1,
      "name": "Budi",
      "role": "seller"
    },
    "body": "Hello, delivering now.",
    "is_system": false,
    "attachments": [],
    "read_at": null,
    "created_at": "2026-10-26T15:54:50Z"
  }
}

Disputes

Disputes and warranty claims on your orders: read the case, its offers, evidence and timeline, and answer as the seller. Money only moves when both sides agree or MythicDeals decides.

List disputes

#
GET /api/v1/disputes
disputes:read

Disputes on your sales, newest first; role=buyer lists the disputes on your purchases instead. awaiting tells who has to act next: seller, buyer, admin (escalated to MythicDeals) or null (finished). Items are a summary with offer_count; get one dispute for its offers, evidence and timeline.

Parameters

NameDescription
role string · query Disputes on your sales (seller) or your purchases (buyer). One of: seller buyer Default: seller
status string · query One status or several separated by commas: open, awaiting_buyer, awaiting_seller, escalated, resolved, closed.
created_since date-time · query Only disputes opened at or after this time.
per_page integer · query Items per page, 1–100. Range: 1–100 · Default: 25
page integer · query Page number. Range: 1–… · Default: 1

Responses

200A page of disputes.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/disputes?status=open%2Cawaiting_seller' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "id": 1,
      "order": {
        "id": 3,
        "number": "48296203",
        "status": "disputed",
        "listing_title": "Immortal 2 account, 42 skins",
        "total_paid_cents": 11999
      },
      "status": "awaiting_buyer",
      "awaiting": "buyer",
      "opener_role": "buyer",
      "category": "not_as_described",
      "category_label": "Not as described",
      "reason": "The rank is Ascendant 3, not Immortal 2 as the listing said.",
      "requested_outcome": "partial_refund",
      "requested_amount_cents": 5000,
      "pending_offer": {
        "id": 1,
        "from_role": "seller",
        "type": "partial_refund",
        "amount_cents": 3000,
        "note": "The rank dropped after the last act; I can refund $30.",
        "status": "pending",
        "created_at": "2026-10-27T12:37:56Z",
        "updated_at": "2026-10-27T12:37:56Z"
      },
      "resolution": null,
      "resolved_amount_cents": null,
      "resolution_note": null,
      "currency": "USD",
      "escalated_at": null,
      "resolved_at": null,
      "created_at": "2026-10-27T12:26:56Z",
      "updated_at": "2026-10-27T12:37:56Z",
      "offer_count": 1
    }
  ],
  "links": {
    "first": "http://localhost:8000/api/v1/disputes?page=1",
    "last": "http://localhost:8000/api/v1/disputes?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "page": null,
        "active": false
      },
      {
        "url": "http://localhost:8000/api/v1/disputes?page=1",
        "label": "1",
        "page": 1,
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "page": null,
        "active": false
      }
    ],
    "path": "http://localhost:8000/api/v1/disputes",
    "per_page": 25,
    "to": 1,
    "total": 1
  }
}

Get a dispute

#
GET /api/v1/disputes/{id}
disputes:read

One dispute where you are the seller or the buyer, with every offer (newest state of each), the evidence files (details and download_url) and the full timeline. A counter-offer of type redeliver has amount_cents: 0: no money back, the seller fixes the delivery.

Parameters

NameDescription
idrequired integer · path Dispute id.

Responses

200The dispute.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/disputes/1' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "id": 1,
    "order": {
      "id": 3,
      "number": "48296203",
      "status": "disputed",
      "listing_title": "Immortal 2 account, 42 skins",
      "total_paid_cents": 11999
    },
    "status": "awaiting_buyer",
    "awaiting": "buyer",
    "opener_role": "buyer",
    "category": "not_as_described",
    "category_label": "Not as described",
    "reason": "The rank is Ascendant 3, not Immortal 2 as the listing said.",
    "requested_outcome": "partial_refund",
    "requested_amount_cents": 5000,
    "pending_offer": {
      "id": 1,
      "from_role": "seller",
      "type": "partial_refund",
      "amount_cents": 3000,
      "note": "The rank dropped after the last act; I can refund $30.",
      "status": "pending",
      "created_at": "2026-10-27T12:37:56Z",
      "updated_at": "2026-10-27T12:37:56Z"
    },
    "resolution": null,
    "resolved_amount_cents": null,
    "resolution_note": null,
    "currency": "USD",
    "escalated_at": null,
    "resolved_at": null,
    "created_at": "2026-10-27T12:26:56Z",
    "updated_at": "2026-10-27T12:37:56Z",
    "offers": [
      {
        "id": 1,
        "from_role": "seller",
        "type": "partial_refund",
        "amount_cents": 3000,
        "note": "The rank dropped after the last act; I can refund $30.",
        "status": "pending",
        "created_at": "2026-10-27T12:37:56Z",
        "updated_at": "2026-10-27T12:37:56Z"
      }
    ],
    "evidence": [
      {
        "id": 1,
        "name": "rank.png",
        "mime": "image/png",
        "size": 153,
        "is_image": true,
        "uploaded_by": {
          "id": 2,
          "role": "buyer"
        },
        "from_chat": true,
        "download_url": "http://localhost:8000/api/v1/disputes/1/evidence/1",
        "created_at": "2026-10-27T12:27:56Z"
      }
    ],
    "timeline": [
      {
        "type": "dispute.opened",
        "at": "2026-10-27T12:26:56Z",
        "actor": {
          "id": 2,
          "role": "buyer"
        },
        "data": {
          "category": "not_as_described",
          "reason": "The rank is Ascendant 3, not Immortal 2 as the listing said.",
          "requested_outcome": "partial_refund",
          "requested_amount_cents": 5000
        }
      },
      {
        "type": "message.created",
        "at": "2026-10-27T12:27:56Z",
        "actor": {
          "id": 2,
          "role": "buyer"
        },
        "data": {
          "message_id": 12,
          "body": "Screenshot of the rank right after login.",
          "attachment_count": 1
        }
      },
      {
        "type": "evidence.added",
        "at": "2026-10-27T12:27:56Z",
        "actor": {
          "id": 2,
          "role": "buyer"
        },
        "data": {
          "evidence_id": 1,
          "name": "rank.png",
          "from_chat": true
        }
      },
      {
        "type": "offer.created",
        "at": "2026-10-27T12:37:56Z",
        "actor": {
          "id": 1,
          "role": "seller"
        },
        "data": {
          "offer_id": 1,
          "type": "partial_refund",
          "amount_cents": 3000,
          "note": "The rank dropped after the last act; I can refund $30."
        }
      },
      {
        "type": "message.created",
        "at": "2026-10-27T12:39:56Z",
        "actor": {
          "id": 1,
          "role": "seller"
        },
        "data": {
          "message_id": 14,
          "body": "The rank reset with the new act — see the patch notes. Offering $30 back.",
          "attachment_count": 0
        }
      }
    ]
  }
}

List dispute events

#
GET /api/v1/disputes/{id}/events
disputes:read

The timeline of a dispute, oldest first — the same list as timeline in GET /disputes/{id}. Types: dispute.opened, message.created (order chat messages written since the dispute opened; system messages are left out), evidence.added, offer.created, offer.accepted, offer.rejected, dispute.escalated, dispute.resolved, dispute.closed. actor.role is buyer, seller, admin or system; an admin’s id is never shown.

Parameters

NameDescription
idrequired integer · path Dispute id.

Responses

200The timeline.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/disputes/1/events' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "type": "dispute.opened",
      "at": "2026-10-27T12:26:56Z",
      "actor": {
        "id": 2,
        "role": "buyer"
      },
      "data": {
        "category": "not_as_described",
        "reason": "The rank is Ascendant 3, not Immortal 2 as the listing said.",
        "requested_outcome": "partial_refund",
        "requested_amount_cents": 5000
      }
    },
    {
      "type": "message.created",
      "at": "2026-10-27T12:27:56Z",
      "actor": {
        "id": 2,
        "role": "buyer"
      },
      "data": {
        "message_id": 12,
        "body": "Screenshot of the rank right after login.",
        "attachment_count": 1
      }
    },
    {
      "type": "evidence.added",
      "at": "2026-10-27T12:27:56Z",
      "actor": {
        "id": 2,
        "role": "buyer"
      },
      "data": {
        "evidence_id": 1,
        "name": "rank.png",
        "from_chat": true
      }
    },
    {
      "type": "offer.created",
      "at": "2026-10-27T12:37:56Z",
      "actor": {
        "id": 1,
        "role": "seller"
      },
      "data": {
        "offer_id": 1,
        "type": "partial_refund",
        "amount_cents": 3000,
        "note": "The rank dropped after the last act; I can refund $30."
      }
    },
    {
      "type": "message.created",
      "at": "2026-10-27T12:39:56Z",
      "actor": {
        "id": 1,
        "role": "seller"
      },
      "data": {
        "message_id": 14,
        "body": "The rank reset with the new act — see the patch notes. Offering $30 back.",
        "attachment_count": 0
      }
    }
  ]
}

Download an evidence file

#
GET /api/v1/disputes/{id}/evidence/{evidenceId}
disputes:read

Downloads one evidence file with its original name (Content-Disposition: attachment). Use the download_url of the dispute; it needs your token like any other call. Files that the buyer or you attach in the order chat while the dispute is open become evidence automatically.

Parameters

NameDescription
idrequired integer · path Dispute id.
evidenceIdrequired integer · path Evidence id, from evidence[].id of the dispute.

Responses

200The file (its own content type, e.g. image/png or application/pdf).
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/disputes/1/evidence/1' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -OJ

Example response

200 OK · application/octet-stream
(file download)

Accept the buyer’s request

#
POST /api/v1/disputes/{id}/accept
disputes:write Verified seller

Accepts what the buyer is asking for: their pending offer if there is one; otherwise — when nobody has made an offer yet — the refund they asked for when they opened the dispute (requested_outcome full_refund, or partial_refund of requested_amount_cents). The dispute is settled at once through escrow: the refund goes back to the buyer, the rest is released to you, and the response shows status: resolved.

409 when there is nothing to accept, when the pending offer is your own, when the dispute is escalated or finished, or when the buyer asked for delivery rather than money (requested_outcome: deliver — correct the delivery with PATCH /orders/{order}/delivery or counter with redeliver).

Requires a verified seller account with a verified email address.

Parameters

NameDescription
idrequired integer · path Dispute id.

Responses

200The settled dispute.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/disputes/1/accept' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "id": 2,
    "order": {
      "id": 4,
      "number": "48298437",
      "status": "refunded",
      "listing_title": "Immortal 2 account, 42 skins",
      "total_paid_cents": 11999
    },
    "status": "resolved",
    "awaiting": null,
    "opener_role": "buyer",
    "category": "not_delivered",
    "category_label": "Never delivered",
    "reason": "The login does not work at all.",
    "requested_outcome": "full_refund",
    "requested_amount_cents": null,
    "pending_offer": null,
    "resolution": "refund_full",
    "resolved_amount_cents": 11999,
    "resolution_note": "Agreed between buyer and seller",
    "currency": "USD",
    "escalated_at": null,
    "resolved_at": "2026-10-27T13:06:56Z",
    "created_at": "2026-10-27T13:01:56Z",
    "updated_at": "2026-10-27T13:06:56Z",
    "offers": [
      {
        "id": 2,
        "from_role": "seller",
        "type": "full_refund",
        "amount_cents": 11999,
        "note": "Seller accepted the buyer's request",
        "status": "accepted",
        "created_at": "2026-10-27T13:06:56Z",
        "updated_at": "2026-10-27T13:06:56Z"
      }
    ],
    "evidence": [],
    "timeline": [
      {
        "type": "dispute.opened",
        "at": "2026-10-27T13:01:56Z",
        "actor": {
          "id": 2,
          "role": "buyer"
        },
        "data": {
          "category": "not_delivered",
          "reason": "The login does not work at all.",
          "requested_outcome": "full_refund",
          "requested_amount_cents": null
        }
      },
      {
        "type": "offer.created",
        "at": "2026-10-27T13:06:56Z",
        "actor": {
          "id": 1,
          "role": "seller"
        },
        "data": {
          "offer_id": 2,
          "type": "full_refund",
          "amount_cents": 11999,
          "note": "Seller accepted the buyer's request"
        }
      },
      {
        "type": "offer.accepted",
        "at": "2026-10-27T13:06:56Z",
        "actor": {
          "id": 2,
          "role": "buyer"
        },
        "data": {
          "offer_id": 2
        }
      },
      {
        "type": "dispute.resolved",
        "at": "2026-10-27T13:06:56Z",
        "actor": {
          "id": 2,
          "role": "buyer"
        },
        "data": {
          "resolution": "refund_full",
          "refunded_amount_cents": 11999,
          "note": "Agreed between buyer and seller"
        }
      }
    ]
  }
}

Make a counter-offer

#
POST /api/v1/disputes/{id}/counter
disputes:write Verified seller Idempotency-Key

Proposes a settlement to the buyer: full_refund (the whole order total), partial_refund (amount_cents, more than 0 and less than the order total — otherwise 409), or redeliver (no refund: you fix the delivery; note is required, and with delivery the corrected details are delivered right away, exactly like PATCH /orders/{order}/delivery). A new offer replaces your earlier pending one (kept as superseded). The dispute then waits for the buyer (awaiting: buyer); if they accept a redeliver, the money is released to you. meta.offer_id is the new offer. Escalated or finished disputes → 409.

Requires a verified seller account with a verified email address. Accepts an Idempotency-Key header: retrying with the same key returns the first response.

Parameters

NameDescription
idrequired integer · path Dispute id.
Idempotency-Key string · header Any unique string (e.g. a UUID), max 255 characters. For 24 hours the same key on the same endpoint returns the stored response (header Idempotent-Replayed: true). Same key with a different body → 409 idempotency_conflict. Length: 0–255
typerequired string · body One of: full_refund partial_refund redeliver
amount_cents integer · body Required for partial_refund; less than the order total. Range: 1–…
note string · body Message to the buyer. Required for redeliver. Length: 0–450
delivery object · body redeliver only: the corrected details, delivered right away.

Responses

201The dispute with your new offer.
400Bad request, e.g. invalid_idempotency_key (key longer than 255 characters).
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/disputes/1/counter' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"type":"partial_refund","amount_cents":3000,"note":"The rank dropped after the last act; I can refund $30."}'

Example response

201 Created
{
  "data": {
    "id": 1,
    "order": {
      "id": 3,
      "number": "48296203",
      "status": "disputed",
      "listing_title": "Immortal 2 account, 42 skins",
      "total_paid_cents": 11999
    },
    "status": "awaiting_buyer",
    "awaiting": "buyer",
    "opener_role": "buyer",
    "category": "not_as_described",
    "category_label": "Not as described",
    "reason": "The rank is Ascendant 3, not Immortal 2 as the listing said.",
    "requested_outcome": "partial_refund",
    "requested_amount_cents": 5000,
    "pending_offer": {
      "id": 1,
      "from_role": "seller",
      "type": "partial_refund",
      "amount_cents": 3000,
      "note": "The rank dropped after the last act; I can refund $30.",
      "status": "pending",
      "created_at": "2026-10-27T12:37:56Z",
      "updated_at": "2026-10-27T12:37:56Z"
    },
    "resolution": null,
    "resolved_amount_cents": null,
    "resolution_note": null,
    "currency": "USD",
    "escalated_at": null,
    "resolved_at": null,
    "created_at": "2026-10-27T12:26:56Z",
    "updated_at": "2026-10-27T12:37:56Z",
    "offers": [
      {
        "id": 1,
        "from_role": "seller",
        "type": "partial_refund",
        "amount_cents": 3000,
        "note": "The rank dropped after the last act; I can refund $30.",
        "status": "pending",
        "created_at": "2026-10-27T12:37:56Z",
        "updated_at": "2026-10-27T12:37:56Z"
      }
    ],
    "evidence": [
      {
        "id": 1,
        "name": "rank.png",
        "mime": "image/png",
        "size": 153,
        "is_image": true,
        "uploaded_by": {
          "id": 2,
          "role": "buyer"
        },
        "from_chat": true,
        "download_url": "http://localhost:8000/api/v1/disputes/1/evidence/1",
        "created_at": "2026-10-27T12:27:56Z"
      }
    ],
    "timeline": [
      {
        "type": "dispute.opened",
        "at": "2026-10-27T12:26:56Z",
        "actor": {
          "id": 2,
          "role": "buyer"
        },
        "data": {
          "category": "not_as_described",
          "reason": "The rank is Ascendant 3, not Immortal 2 as the listing said.",
          "requested_outcome": "partial_refund",
          "requested_amount_cents": 5000
        }
      },
      {
        "type": "message.created",
        "at": "2026-10-27T12:27:56Z",
        "actor": {
          "id": 2,
          "role": "buyer"
        },
        "data": {
          "message_id": 12,
          "body": "Screenshot of the rank right after login.",
          "attachment_count": 1
        }
      },
      {
        "type": "evidence.added",
        "at": "2026-10-27T12:27:56Z",
        "actor": {
          "id": 2,
          "role": "buyer"
        },
        "data": {
          "evidence_id": 1,
          "name": "rank.png",
          "from_chat": true
        }
      },
      {
        "type": "offer.created",
        "at": "2026-10-27T12:37:56Z",
        "actor": {
          "id": 1,
          "role": "seller"
        },
        "data": {
          "offer_id": 1,
          "type": "partial_refund",
          "amount_cents": 3000,
          "note": "The rank dropped after the last act; I can refund $30."
        }
      }
    ]
  },
  "meta": {
    "offer_id": 1
  }
}

Escalate to MythicDeals

#
POST /api/v1/disputes/{id}/escalate
disputes:write Verified seller

Asks MythicDeals to review the case and decide. After that neither side can make or accept offers (409), but both can still send messages and evidence. Calling it again on an escalated dispute returns it unchanged. Finished disputes → 409.

Requires a verified seller account with a verified email address.

Parameters

NameDescription
idrequired integer · path Dispute id.

Responses

200The escalated dispute.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/disputes/1/escalate' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "id": 1,
    "order": {
      "id": 3,
      "number": "48296203",
      "status": "disputed",
      "listing_title": "Immortal 2 account, 42 skins",
      "total_paid_cents": 11999
    },
    "status": "escalated",
    "awaiting": "admin",
    "opener_role": "buyer",
    "category": "not_as_described",
    "category_label": "Not as described",
    "reason": "The rank is Ascendant 3, not Immortal 2 as the listing said.",
    "requested_outcome": "partial_refund",
    "requested_amount_cents": 5000,
    "pending_offer": {
      "id": 1,
      "from_role": "seller",
      "type": "partial_refund",
      "amount_cents": 3000,
      "note": "The rank dropped after the last act; I can refund $30.",
      "status": "pending",
      "created_at": "2026-10-27T12:37:56Z",
      "updated_at": "2026-10-27T12:37:56Z"
    },
    "resolution": null,
    "resolved_amount_cents": null,
    "resolution_note": null,
    "currency": "USD",
    "escalated_at": "2026-10-27T12:41:56Z",
    "resolved_at": null,
    "created_at": "2026-10-27T12:26:56Z",
    "updated_at": "2026-10-27T12:41:56Z",
    "offers": [
      {
        "id": 1,
        "from_role": "seller",
        "type": "partial_refund",
        "amount_cents": 3000,
        "note": "The rank dropped after the last act; I can refund $30.",
        "status": "pending",
        "created_at": "2026-10-27T12:37:56Z",
        "updated_at": "2026-10-27T12:37:56Z"
      }
    ],
    "evidence": [
      {
        "id": 1,
        "name": "rank.png",
        "mime": "image/png",
        "size": 153,
        "is_image": true,
        "uploaded_by": {
          "id": 2,
          "role": "buyer"
        },
        "from_chat": true,
        "download_url": "http://localhost:8000/api/v1/disputes/1/evidence/1",
        "created_at": "2026-10-27T12:27:56Z"
      }
    ],
    "timeline": [
      {
        "type": "dispute.opened",
        "at": "2026-10-27T12:26:56Z",
        "actor": {
          "id": 2,
          "role": "buyer"
        },
        "data": {
          "category": "not_as_described",
          "reason": "The rank is Ascendant 3, not Immortal 2 as the listing said.",
          "requested_outcome": "partial_refund",
          "requested_amount_cents": 5000
        }
      },
      {
        "type": "message.created",
        "at": "2026-10-27T12:27:56Z",
        "actor": {
          "id": 2,
          "role": "buyer"
        },
        "data": {
          "message_id": 12,
          "body": "Screenshot of the rank right after login.",
          "attachment_count": 1
        }
      },
      {
        "type": "evidence.added",
        "at": "2026-10-27T12:27:56Z",
        "actor": {
          "id": 2,
          "role": "buyer"
        },
        "data": {
          "evidence_id": 1,
          "name": "rank.png",
          "from_chat": true
        }
      },
      {
        "type": "offer.created",
        "at": "2026-10-27T12:37:56Z",
        "actor": {
          "id": 1,
          "role": "seller"
        },
        "data": {
          "offer_id": 1,
          "type": "partial_refund",
          "amount_cents": 3000,
          "note": "The rank dropped after the last act; I can refund $30."
        }
      },
      {
        "type": "message.created",
        "at": "2026-10-27T12:39:56Z",
        "actor": {
          "id": 1,
          "role": "seller"
        },
        "data": {
          "message_id": 14,
          "body": "The rank reset with the new act — see the patch notes. Offering $30 back.",
          "attachment_count": 0
        }
      },
      {
        "type": "dispute.escalated",
        "at": "2026-10-27T12:41:56Z",
        "actor": {
          "id": 1,
          "role": "seller"
        },
        "data": []
      }
    ]
  }
}

Send a dispute message

#
POST /api/v1/disputes/{id}/messages
disputes:write Verified seller Idempotency-Key

Writes in the chat of the disputed order (the dispute room), as the seller. Text, files (multipart) or both — the same rules as POST /orders/{order}/messages. Files you attach become dispute evidence automatically. 409 chat_closed when the order chat is closed.

Requires a verified seller account with a verified email address. Accepts an Idempotency-Key header: retrying with the same key returns the first response.

Parameters

NameDescription
idrequired integer · path Dispute id.
Idempotency-Key string · header Any unique string (e.g. a UUID), max 255 characters. For 24 hours the same key on the same endpoint returns the stored response (header Idempotent-Replayed: true). Same key with a different body → 409 idempotency_conflict. Length: 0–255
body string · body Message text. Required unless you send files. Length: 0–2000
files[] file[] · body · multipart JPG, PNG, WebP or PDF, max 5 files, 4 MB each. They become evidence. Max items: 5

Responses

201The new message.
400Bad request, e.g. invalid_idempotency_key (key longer than 255 characters).
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/disputes/1/messages' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"body":"The rank reset with the new act — see the patch notes. Offering $30 back."}'

Example response

201 Created
{
  "data": {
    "id": 14,
    "order_id": 3,
    "sender": {
      "id": 1,
      "name": "Budi",
      "role": "seller"
    },
    "body": "The rank reset with the new act — see the patch notes. Offering $30 back.",
    "is_system": false,
    "attachments": [],
    "read_at": null,
    "created_at": "2026-10-27T12:39:56Z"
  }
}

Wallet

Balances and ledger. Same numbers as the Wallet page.

Get balances

#
GET /api/v1/wallet
wallet:read

available_cents can be withdrawn. pending_cents is money from orders not released yet — it includes warranty_held_cents (completed orders still under warranty). frozen_cents is held by open disputes.

Responses

200Balances in USD cents.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/wallet' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "available_cents": 25400,
    "pending_cents": 18000,
    "frozen_cents": 0,
    "warranty_held_cents": 9000,
    "currency": "USD"
  }
}

List ledger entries

#
GET /api/v1/wallet/ledger
wallet:read

Every change to your available balance, newest first. Debits have a negative amount_cents.

Parameters

NameDescription
type string · query Only entries of this type. One of: sale_credit refund_debit withdrawal_debit withdrawal_revert adjustment affiliate_commission
per_page integer · query Items per page, 1–100. Range: 1–100 · Default: 25
page integer · query Page number. Range: 1–… · Default: 1

Responses

200A page of entries.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/wallet/ledger' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "id": 41,
      "type": "sale_credit",
      "amount_cents": 9000,
      "balance_after_cents": 25400,
      "currency": "USD",
      "description": "Sale 48291735",
      "order": {
        "id": 1,
        "number": "48291735"
      },
      "withdrawal_id": null,
      "created_at": "2026-10-29T15:54:50Z"
    }
  ],
  "links": {
    "first": "http://localhost:8000/api/v1/wallet/ledger?page=1",
    "last": "http://localhost:8000/api/v1/wallet/ledger?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "page": null,
        "active": false
      },
      {
        "url": "http://localhost:8000/api/v1/wallet/ledger?page=1",
        "label": "1",
        "page": 1,
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "page": null,
        "active": false
      }
    ],
    "path": "http://localhost:8000/api/v1/wallet/ledger",
    "per_page": 25,
    "to": 1,
    "total": 1
  }
}

Payouts

Withdrawals from your wallet to your bank or e-wallet. Read-only: request payouts on the website (two-factor and tax checks).

List payouts

#
GET /api/v1/payouts
wallet:read

Your withdrawals, newest first — the same list as on the Wallet page. A payout goes requested → approved → completed (money sent, transfer_reference set), or ends rejected / failed (reject_reason set; the amount returns to your balance). method.label is masked.

Parameters

NameDescription
status string · query One status or several separated by commas: requested, approved, completed, rejected, failed.
created_since date-time · query Only payouts requested at or after this time.
per_page integer · query Items per page, 1–100. Range: 1–100 · Default: 25
page integer · query Page number. Range: 1–… · Default: 1

Responses

200A page of payouts.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/payouts' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "id": 2,
      "status": "requested",
      "status_label": "Waiting for review",
      "amount_cents": 12000,
      "fee_cents": 120,
      "net_amount_cents": 11880,
      "currency": "USD",
      "method": {
        "type": "ewallet",
        "label": "DANA ••••7781"
      },
      "transfer_reference": null,
      "reject_reason": null,
      "created_at": "2026-10-27T13:32:56Z",
      "reviewed_at": null,
      "paid_at": null,
      "updated_at": "2026-10-27T13:32:56Z"
    },
    {
      "id": 1,
      "status": "completed",
      "status_label": "Sent",
      "amount_cents": 25000,
      "fee_cents": 250,
      "net_amount_cents": 24750,
      "currency": "USD",
      "method": {
        "type": "bank",
        "label": "BCA ••••1234"
      },
      "transfer_reference": "TRX-20261025-0042",
      "reject_reason": null,
      "created_at": "2026-10-24T13:32:56Z",
      "reviewed_at": "2026-10-24T15:32:56Z",
      "paid_at": "2026-10-25T13:32:56Z",
      "updated_at": "2026-10-25T13:32:56Z"
    }
  ],
  "links": {
    "first": "http://localhost:8000/api/v1/payouts?page=1",
    "last": "http://localhost:8000/api/v1/payouts?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "page": null,
        "active": false
      },
      {
        "url": "http://localhost:8000/api/v1/payouts?page=1",
        "label": "1",
        "page": 1,
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "page": null,
        "active": false
      }
    ],
    "path": "http://localhost:8000/api/v1/payouts",
    "per_page": 25,
    "to": 2,
    "total": 2
  }
}

Get a payout

#
GET /api/v1/payouts/{id}
wallet:read

Parameters

NameDescription
idrequired integer · path Payout id.

Responses

200The payout.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/payouts/1' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "id": 1,
    "status": "completed",
    "status_label": "Sent",
    "amount_cents": 25000,
    "fee_cents": 250,
    "net_amount_cents": 24750,
    "currency": "USD",
    "method": {
      "type": "bank",
      "label": "BCA ••••1234"
    },
    "transfer_reference": "TRX-20261025-0042",
    "reject_reason": null,
    "created_at": "2026-10-24T13:32:56Z",
    "reviewed_at": "2026-10-24T15:32:56Z",
    "paid_at": "2026-10-25T13:32:56Z",
    "updated_at": "2026-10-25T13:32:56Z"
  }
}

Notifications

Your notification bell: order updates and support replies, the same list as on the website.

List notifications

#
GET /api/v1/notifications
notifications:read

Your notification bell, newest first: order events (id starting with e, type = the order’s new status, e.g. paid, delivered, disputed) and support ticket replies (id starting with t, type: support). unread=1 returns only unread ones. meta.unread_count is the number on the bell. Not paginated: use limit (1–100, default 25) for the most recent items.

Parameters

NameDescription
unread boolean · query Only unread notifications. Default: false
limit integer · query How many to return. Range: 1–100 · Default: 25

Responses

200Notifications.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/notifications?unread=1' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "id": "e25",
      "type": "disputed",
      "title": "Delivery details updated",
      "body": "The seller corrected the delivery details — check them again.",
      "item": "Immortal 2 account, 42 skins",
      "counterparty": {
        "role": "seller",
        "name": "Budi Store"
      },
      "order_number": "48297320",
      "ticket_number": null,
      "amount_cents": 11999,
      "currency": "USD",
      "url": "http://localhost:8000/orders/5",
      "unread": true,
      "created_at": "2026-10-27T13:31:56Z"
    },
    {
      "id": "e23",
      "type": "delivered",
      "title": "Order delivered",
      "body": "Delivered — check it, then confirm.",
      "item": "Immortal 2 account, 42 skins",
      "counterparty": {
        "role": "seller",
        "name": "Budi Store"
      },
      "order_number": "48297320",
      "ticket_number": null,
      "amount_cents": 11999,
      "currency": "USD",
      "url": "http://localhost:8000/orders/5",
      "unread": true,
      "created_at": "2026-10-27T13:16:56Z"
    },
    {
      "id": "e22",
      "type": "processing",
      "title": "Order in progress",
      "body": "The seller started working on it.",
      "item": "Immortal 2 account, 42 skins",
      "counterparty": {
        "role": "seller",
        "name": "Budi Store"
      },
      "order_number": "48297320",
      "ticket_number": null,
      "amount_cents": 11999,
      "currency": "USD",
      "url": "http://localhost:8000/orders/5",
      "unread": true,
      "created_at": "2026-10-27T13:16:56Z"
    }
  ],
  "meta": {
    "limit": 3,
    "unread_count": 17
  }
}

Mark notifications as read

#
POST /api/v1/notifications/read
notifications:write

Without a body: marks everything as read, like “Mark all as read” on the website. With ids (up to 100 order-event ids, starting with e): marks only those; ids that are not yours are ignored and marked counts the ones that were. Support replies cannot be marked one by one. Returns the new unread_count.

Parameters

NameDescription
ids string[] · body Order-event notification ids. Leave out to mark everything. Max items: 100

Responses

200The new unread count.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/notifications/read' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"ids":["e22"]}'

Example response

200 OK
{
  "data": {
    "all": false,
    "marked": 1,
    "unread_count": 16
  }
}

Boosting

Boosting works by request: buyers post their current rank, target and options, boosters send a price and a time. Read open requests, send or withdraw offers, and post progress on the orders you win.

List open boosting requests

#
GET /api/v1/boosting/requests
boosting:read Verified seller

Open requests from buyers, newest first (never your own). mine=1 keeps only the games you boost. range is the current → target rank or level with the number of steps; my_offer is your offer on it, if any.

Requires a verified seller account with a verified email address.

Parameters

NameDescription
game_id integer · query Only this game.
service string · query boost, coaching or custom. One of: boost coaching custom
mine boolean · query Only the games you boost.
per_page integer · query Items per page, 1–100. Range: 1–100 · Default: 25
page integer · query Page number. Range: 1–… · Default: 1

Responses

200A page of open requests.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/boosting/requests' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "id": 12,
      "game": {
        "id": 3,
        "name": "Valorant",
        "slug": "valorant"
      },
      "category_id": 9,
      "service": "boost",
      "title": "Valorant — Rank boost: Silver → Diamond (EU, Solo)",
      "range": {
        "from": "Silver",
        "to": "Diamond",
        "steps": 3
      },
      "details": {
        "region": "EU",
        "rank_from": "Silver",
        "rank_to": "Diamond",
        "queue": "Solo"
      },
      "options": {
        "stream": true
      },
      "notes": "I mostly play Jett and Sova. Evenings CET work best.",
      "budget_cents": 4500,
      "deadline_hours": 72,
      "offers_count": 2,
      "my_offer": null,
      "status": "open",
      "expires_at": "2026-11-02T12:00:00+00:00",
      "created_at": "2026-10-30T12:00:00+00:00",
      "url": "https://mythicdeals.example/boosting/requests/12"
    }
  ],
  "meta": {
    "current_page": 1,
    "last_page": 1,
    "total": 1
  }
}

Get a boosting request

#
GET /api/v1/boosting/requests/{id}
boosting:read Verified seller

One open request, or a closed one you made an offer on. Your own requests → 404.

Requires a verified seller account with a verified email address.

Parameters

NameDescription
idrequired integer · path Boosting request id.

Responses

200The request.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/boosting/requests/12' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "id": 12,
    "game": {
      "id": 3,
      "name": "Valorant",
      "slug": "valorant"
    },
    "category_id": 9,
    "service": "boost",
    "title": "Valorant — Rank boost: Silver → Diamond (EU, Solo)",
    "range": {
      "from": "Silver",
      "to": "Diamond",
      "steps": 3
    },
    "details": {
      "region": "EU",
      "rank_from": "Silver",
      "rank_to": "Diamond",
      "queue": "Solo"
    },
    "options": {
      "stream": true
    },
    "notes": "I mostly play Jett and Sova. Evenings CET work best.",
    "budget_cents": 4500,
    "deadline_hours": 72,
    "offers_count": 2,
    "my_offer": null,
    "status": "open",
    "expires_at": "2026-11-02T12:00:00+00:00",
    "created_at": "2026-10-30T12:00:00+00:00",
    "url": "https://mythicdeals.example/boosting/requests/12"
  }
}

List your boosting offers

#
GET /api/v1/boosting/offers
boosting:read Verified seller

Your offers, last changed first. An accepted offer has the order_id of the order it became — deliver it like any other order.

Requires a verified seller account with a verified email address.

Parameters

NameDescription
status string · query Only this status. One of: pending accepted declined withdrawn expired
per_page integer · query Items per page, 1–100. Range: 1–100 · Default: 25
page integer · query Page number. Range: 1–… · Default: 1

Responses

200A page of offers.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/boosting/offers' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "id": 31,
      "price_cents": 3800,
      "eta_hours": 48,
      "message": "Immortal 3 EU, I can start tonight and stream every game.",
      "status": "pending",
      "revisions": 0,
      "updated_at": "2026-10-30T12:05:00+00:00",
      "request_id": 12,
      "request_title": "Valorant — Rank boost: Silver → Diamond (EU, Solo)",
      "order_id": null
    }
  ],
  "meta": {
    "current_page": 1,
    "last_page": 1,
    "total": 1
  }
}

Send or update an offer

#
POST /api/v1/boosting/requests/{id}/offer
boosting:write Verified seller

Your price (USD cents) and completion time for a request. Sending again updates your offer (201 the first time, 200 after) and the buyer is notified when the price or time changes. eta_hours must be one of the listed values. Closed request, your own request, store on a break → 409.

Requires a verified seller account with a verified email address.

Parameters

NameDescription
idrequired integer · path Boosting request id.
price_centsrequired integer · body Range: 100–1000000
eta_hoursrequired integer · body One of: 1 2 3 6 12 24 48 72 96 120 168 240 336 504 720
message string · body Length: 0–1000

Responses

201Your offer.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/boosting/requests/12/offer' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"price_cents":3800,"eta_hours":48,"message":"Immortal 3 EU, I can start tonight and stream every game."}'

Example response

201 Created
{
  "data": {
    "id": 31,
    "price_cents": 3800,
    "eta_hours": 48,
    "message": "Immortal 3 EU, I can start tonight and stream every game.",
    "status": "pending",
    "revisions": 0,
    "updated_at": "2026-10-30T12:05:00+00:00"
  }
}

Withdraw an offer

#
POST /api/v1/boosting/offers/{id}/withdraw
boosting:write Verified seller

Withdraws a pending offer. While the request is open you can send a new one. Not pending → 409.

Requires a verified seller account with a verified email address.

Parameters

NameDescription
idrequired integer · path Boosting offer id.

Responses

200The withdrawn offer.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/boosting/offers/31/withdraw' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "status": "withdrawn",
    "id": 31,
    "price_cents": 3800,
    "eta_hours": 48,
    "message": "Immortal 3 EU, I can start tonight and stream every game.",
    "revisions": 0,
    "updated_at": "2026-10-30T12:05:00+00:00"
  }
}

Post boost progress

#
POST /api/v1/boosting/orders/{id}/progress
boosting:write Verified seller

Shares progress on a boosting order you sell: percent done and the current rank or level. The buyer sees a progress bar and is notified. A paid order is started automatically. Only while the order is paid or in progress (otherwise 409).

Requires a verified seller account with a verified email address.

Parameters

NameDescription
idrequired integer · path Order id.
percentrequired integer · body Range: 0–100
current string · body Length: 0–80
note string · body Length: 0–500

Responses

201The progress update.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/boosting/orders/120/progress' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"percent":50,"current":"Platinum 2","note":"Halfway there, 8 wins in a row."}'

Example response

201 Created
{
  "data": {
    "id": 4,
    "order_id": 120,
    "percent": 50,
    "current": "Platinum 2",
    "note": "Halfway there, 8 wins in a row.",
    "created_at": "2026-10-31T19:20:00+00:00"
  }
}

Webhooks

Manage the HTTPS endpoints that receive signed event notifications.

List webhook endpoints

#
GET /api/v1/webhooks
webhooks:write

All your endpoints (at most 10). Not paginated. Secrets are never returned here, only secret_hint.

Responses

200Your endpoints.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/webhooks' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "id": 1,
      "url": "https://hooks.example.com/mythicdeals",
      "description": "Sync bot",
      "events": [
        "order.paid",
        "message.created"
      ],
      "is_active": true,
      "failure_count": 0,
      "disabled_at": null,
      "last_success_at": null,
      "last_failure_at": null,
      "secret_hint": "whsec_3kT…",
      "created_at": "2026-10-26T15:54:50Z",
      "updated_at": "2026-10-26T15:54:50Z"
    }
  ]
}

Create a webhook endpoint

#
POST /api/v1/webhooks
webhooks:write Idempotency-Key

The URL must use HTTPS, must not contain a username or password, and must resolve to a public IP address. The response contains the signing secret — the only time it is shown. At most 10 endpoints per account.

Accepts an Idempotency-Key header: retrying with the same key returns the first response.

Parameters

NameDescription
Idempotency-Key string · header Any unique string (e.g. a UUID), max 255 characters. For 24 hours the same key on the same endpoint returns the stored response (header Idempotent-Replayed: true). Same key with a different body → 409 idempotency_conflict. Length: 0–255
urlrequired string · body HTTPS URL that resolves to a public IP. Length: 0–500
eventsrequired string[] · body Events to receive.
description string | null · body A note for yourself. Length: 0–120

Responses

201The new endpoint, with its secret.
400Bad request, e.g. invalid_idempotency_key (key longer than 255 characters).
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/webhooks' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://hooks.example.com/mythicdeals","events":["order.paid","message.created"],"description":"Sync bot"}'

Example response

201 Created
{
  "data": {
    "id": 1,
    "url": "https://hooks.example.com/mythicdeals",
    "description": "Sync bot",
    "events": [
      "order.paid",
      "message.created"
    ],
    "is_active": true,
    "failure_count": 0,
    "disabled_at": null,
    "last_success_at": null,
    "last_failure_at": null,
    "secret_hint": "whsec_3kT…",
    "secret": "whsec_3kTqL9vWm2YbX7pRz4NcF8hJd1GsA6eQ0uVoK5iE",
    "created_at": "2026-10-26T15:54:50Z",
    "updated_at": "2026-10-26T15:54:50Z"
  }
}

Get a webhook endpoint

#
GET /api/v1/webhooks/{webhook}
webhooks:write

Parameters

NameDescription
webhookrequired integer · path Webhook endpoint id.

Responses

200The endpoint.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/webhooks/1' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "id": 1,
    "url": "https://hooks.example.com/mythicdeals",
    "description": "Sync bot",
    "events": [
      "order.paid",
      "message.created"
    ],
    "is_active": true,
    "failure_count": 0,
    "disabled_at": null,
    "last_success_at": null,
    "last_failure_at": null,
    "secret_hint": "whsec_3kT…",
    "created_at": "2026-10-26T15:54:50Z",
    "updated_at": "2026-10-26T15:54:50Z"
  }
}

Update a webhook endpoint

#
PATCH /api/v1/webhooks/{webhook}
webhooks:write

Change the URL, events, description or is_active. Turning an endpoint back on resets its failure count. rotate_secret: true issues a new secret (returned once in secret); the old one stops working immediately.

Parameters

NameDescription
webhookrequired integer · path Webhook endpoint id.
url string · body HTTPS URL that resolves to a public IP. Length: 0–500
events string[] · body Replaces the event list.
description string | null · body A note for yourself. Length: 0–120
is_active boolean · body Turn on/off. Turning on resets failure_count.
rotate_secret boolean · body true: issue a new secret (old one stops working).

Responses

200The updated endpoint.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X PATCH 'https://mythicdeals.com/api/v1/webhooks/1' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"events":["order.paid"],"rotate_secret":true}'

Example response

200 OK
{
  "data": {
    "id": 1,
    "url": "https://hooks.example.com/mythicdeals",
    "description": "Sync bot",
    "events": [
      "order.paid"
    ],
    "is_active": true,
    "failure_count": 0,
    "disabled_at": null,
    "last_success_at": null,
    "last_failure_at": null,
    "secret_hint": "whsec_3kT…",
    "secret": "whsec_3kTqL9vWm2YbX7pRz4NcF8hJd1GsA6eQ0uVoK5iE",
    "created_at": "2026-10-26T15:54:50Z",
    "updated_at": "2026-10-26T15:54:50Z"
  }
}

Delete a webhook endpoint

#
DELETE /api/v1/webhooks/{webhook}
webhooks:write

Deletes the endpoint and its delivery history.

Parameters

NameDescription
webhookrequired integer · path Webhook endpoint id.

Responses

204Deleted. No body.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X DELETE 'https://mythicdeals.com/api/v1/webhooks/1' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

204 No Content
(no body)

Send a test event

#
POST /api/v1/webhooks/{webhook}/test
webhooks:write

Sends a signed ping event right now and returns the delivery result. Works even when the endpoint is turned off. Pings are not retried and do not count as failures.

Parameters

NameDescription
webhookrequired integer · path Webhook endpoint id.

Responses

200The ping delivery.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/webhooks/1/test' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "id": 1,
    "delivery_id": "dlv_01m5weqvzdvzns8870e41gv24h",
    "event": "ping",
    "status": "succeeded",
    "attempts": 1,
    "response_code": 200,
    "response_excerpt": "ok",
    "error": null,
    "next_attempt_at": null,
    "delivered_at": "2026-10-26T15:54:50Z",
    "payload": {
      "id": "evt_01m5weqvzcma48d9m8tfm3bjv9",
      "type": "ping",
      "created_at": "2026-10-26T15:54:50Z",
      "data": {
        "message": "Webhook test from MythicDeals.",
        "endpoint_id": 1
      }
    },
    "created_at": "2026-10-26T15:54:50Z"
  }
}

List deliveries

#
GET /api/v1/webhooks/{webhook}/deliveries
webhooks:write

Delivery attempts of one endpoint, newest first, with the payload, last response code and next retry time.

Parameters

NameDescription
webhookrequired integer · path Webhook endpoint id.
status string · query Only deliveries with this status. One of: pending sending succeeded failed
event string · query Only this event type, e.g. order.paid. Length: 0–40
per_page integer · query Items per page, 1–100. Range: 1–100 · Default: 25
page integer · query Page number. Range: 1–… · Default: 1

Responses

200A page of deliveries.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
422Validation failed. Laravel format: a message and errors per field.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl 'https://mythicdeals.com/api/v1/webhooks/1/deliveries?status=failed' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": [
    {
      "id": 1,
      "delivery_id": "dlv_01m5weqvzdvzns8870e41gv24h",
      "event": "ping",
      "status": "succeeded",
      "attempts": 1,
      "response_code": 200,
      "response_excerpt": "ok",
      "error": null,
      "next_attempt_at": null,
      "delivered_at": "2026-10-26T15:54:50Z",
      "payload": {
        "id": "evt_01m5weqvzcma48d9m8tfm3bjv9",
        "type": "ping",
        "created_at": "2026-10-26T15:54:50Z",
        "data": {
          "message": "Webhook test from MythicDeals.",
          "endpoint_id": 1
        }
      },
      "created_at": "2026-10-26T15:54:50Z"
    }
  ],
  "links": {
    "first": "http://localhost:8000/api/v1/webhooks/1/deliveries?page=1",
    "last": "http://localhost:8000/api/v1/webhooks/1/deliveries?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Previous",
        "page": null,
        "active": false
      },
      {
        "url": "http://localhost:8000/api/v1/webhooks/1/deliveries?page=1",
        "label": "1",
        "page": 1,
        "active": true
      },
      {
        "url": null,
        "label": "Next &raquo;",
        "page": null,
        "active": false
      }
    ],
    "path": "http://localhost:8000/api/v1/webhooks/1/deliveries",
    "per_page": 25,
    "to": 1,
    "total": 1
  }
}

Retry a delivery

#
POST /api/v1/webhooks/{webhook}/deliveries/{delivery}/retry
webhooks:write

Tries a failed or waiting delivery again right now. The endpoint must be turned on. Other statuses return 409.

Parameters

NameDescription
webhookrequired integer · path Webhook endpoint id.
deliveryrequired string · path Delivery id (number) or delivery_id (dlv_…).

Responses

200The delivery after the new attempt.
401unauthenticated: the token is missing, invalid, expired or revoked.
403insufficient_scope (with required_scope), seller_not_verified, email_not_verified or account_suspended.
404not_found: it does not exist or belongs to someone else.
409conflict (the action is not possible in the current state), chat_closed, preview_expired (CSV import), idempotency_conflict or idempotency_in_progress.
429rate_limited: too many requests. Wait Retry-After seconds.

Example request

curl -X POST 'https://mythicdeals.com/api/v1/webhooks/1/deliveries/dlv_01m5weqvzdvzns8870e41gv24h/retry' \
  -H "Authorization: Bearer $MYTHICDEALS_TOKEN" \
  -H "Accept: application/json"

Example response

200 OK
{
  "data": {
    "id": 1,
    "delivery_id": "dlv_01m5weqvzdvzns8870e41gv24h",
    "event": "ping",
    "status": "succeeded",
    "attempts": 1,
    "response_code": 200,
    "response_excerpt": "ok",
    "error": null,
    "next_attempt_at": null,
    "delivered_at": "2026-10-26T15:54:50Z",
    "payload": {
      "id": "evt_01m5weqvzcma48d9m8tfm3bjv9",
      "type": "ping",
      "created_at": "2026-10-26T15:54:50Z",
      "data": {
        "message": "Webhook test from MythicDeals.",
        "endpoint_id": 1
      }
    },
    "created_at": "2026-10-26T15:54:50Z"
  }
}