{
  "openapi": "3.1.0",
  "info": {
    "title": "Spoofy API",
    "version": "1.0.0",
    "summary": "Growth for any link — followers, views, likes, members, reactions and visits — from code or an AI agent.",
    "description": "Everything the Spoofy web app does, a program or an agent can do. Three ways in:\n\n- **REST** (this document) at `https://spoofy.social/api/v1`.\n- **SMM-compatible** endpoint at `https://spoofy.social/api/v2` (`key` + `action`), so the SMM tools you already use plug Spoofy in with no code.\n- **MCP** server at `https://spoofy.social/mcp` (Streamable HTTP) for Claude, Cursor and any MCP client.\n\nMoney is US dollars, always as a decimal string (`\"4.99\"`). Orders spend real balance; use `dry_run: true` to validate and price without charging.\nErrors are `{\"error\": {\"code\", \"message\", \"details?\"}}` with a meaningful HTTP status.",
    "contact": {
      "url": "https://spoofy.social/developers"
    }
  },
  "servers": [
    {
      "url": "https://spoofy.social",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Catalog",
      "description": "What can be bought, for which link, at what price. No auth needed."
    },
    {
      "name": "Orders",
      "description": "Place, read, refill and cancel orders. Spends balance."
    },
    {
      "name": "Account",
      "description": "Balance."
    },
    {
      "name": "Deposits",
      "description": "Top up the balance with USDG (Robinhood Chain) or the project token (10 % off)."
    },
    {
      "name": "API keys",
      "description": "Create and revoke keys. Signed-in dashboard session only — a key cannot mint keys."
    },
    {
      "name": "Webhooks",
      "description": "Signed event delivery to your endpoint. Session only."
    },
    {
      "name": "SMM-compatible",
      "description": "The SMM-standard `key` + `action` endpoint."
    },
    {
      "name": "Meta",
      "description": "This document."
    }
  ],
  "security": [
    {
      "apiKey": []
    },
    {
      "session": []
    }
  ],
  "paths": {
    "/api/v1/services": {
      "get": {
        "operationId": "listServices",
        "summary": "List services",
        "description": "The full public catalog: every service with its price per 1,000, range and package suggestions.",
        "tags": [
          "Catalog"
        ],
        "security": [],
        "parameters": [
          {
            "name": "platform",
            "in": "query",
            "description": "Only one platform, e.g. `x`, `tiktok`, `telegram`.",
            "schema": {
              "type": "string"
            },
            "example": "x"
          }
        ],
        "responses": {
          "200": {
            "description": "The catalog.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "services": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Service"
                      }
                    }
                  }
                },
                "example": {
                  "services": [
                    {
                      "id": 12,
                      "platform": "x",
                      "platformLabel": "X",
                      "target": "profile",
                      "metric": "followers",
                      "metricLabel": "Followers",
                      "tier": "standard",
                      "name": "X Followers — Standard",
                      "description": "Real-looking accounts, steady delivery, 30-day refill.",
                      "linkHint": "https://x.com/yourname",
                      "minQty": 100,
                      "maxQty": 50000,
                      "pricePer1k": "4.99",
                      "pricePer1kMicros": "4990000",
                      "refillDays": 30,
                      "refillable": true,
                      "cancelable": true,
                      "startTime": "0–2 h",
                      "speed": "2K / day",
                      "tags": [
                        "refill"
                      ],
                      "startEstimate": "Usually starts within 1 h",
                      "delivery": {
                        "startMinutes": 60,
                        "perDay": 2000,
                        "avgMinutesPer1k": null
                      },
                      "packages": [
                        {
                          "quantity": 100,
                          "price": "0.50",
                          "eta": "~3 h",
                          "etaMinutes": 132
                        },
                        {
                          "quantity": 500,
                          "price": "2.50",
                          "eta": "~7 h",
                          "etaMinutes": 420
                        },
                        {
                          "quantity": 1000,
                          "price": "4.99",
                          "eta": "~13 h",
                          "etaMinutes": 780
                        },
                        {
                          "quantity": 5000,
                          "price": "24.95",
                          "eta": "~3 days",
                          "etaMinutes": 3660
                        },
                        {
                          "quantity": 50000,
                          "price": "249.50",
                          "eta": "~25 days",
                          "etaMinutes": 36060
                        }
                      ]
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/Internal"
          }
        }
      }
    },
    "/api/v1/services/{id}": {
      "get": {
        "operationId": "getService",
        "summary": "Get a service",
        "description": "One service by id.",
        "tags": [
          "Catalog"
        ],
        "security": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Service id.",
            "schema": {
              "type": "integer"
            },
            "example": 12
          }
        ],
        "responses": {
          "200": {
            "description": "The service.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "service": {
                      "$ref": "#/components/schemas/Service"
                    }
                  }
                },
                "example": {
                  "service": {
                    "id": 12,
                    "platform": "x",
                    "platformLabel": "X",
                    "target": "profile",
                    "metric": "followers",
                    "metricLabel": "Followers",
                    "tier": "standard",
                    "name": "X Followers — Standard",
                    "description": "Real-looking accounts, steady delivery, 30-day refill.",
                    "linkHint": "https://x.com/yourname",
                    "minQty": 100,
                    "maxQty": 50000,
                    "pricePer1k": "4.99",
                    "pricePer1kMicros": "4990000",
                    "refillDays": 30,
                    "refillable": true,
                    "cancelable": true,
                    "startTime": "0–2 h",
                    "speed": "2K / day",
                    "tags": [
                      "refill"
                    ],
                    "startEstimate": "Usually starts within 1 h",
                    "delivery": {
                      "startMinutes": 60,
                      "perDay": 2000,
                      "avgMinutesPer1k": null
                    },
                    "packages": [
                      {
                        "quantity": 100,
                        "price": "0.50",
                        "eta": "~3 h",
                        "etaMinutes": 132
                      },
                      {
                        "quantity": 500,
                        "price": "2.50",
                        "eta": "~7 h",
                        "etaMinutes": 420
                      },
                      {
                        "quantity": 1000,
                        "price": "4.99",
                        "eta": "~13 h",
                        "etaMinutes": 780
                      },
                      {
                        "quantity": 5000,
                        "price": "24.95",
                        "eta": "~3 days",
                        "etaMinutes": 3660
                      },
                      {
                        "quantity": 50000,
                        "price": "249.50",
                        "eta": "~25 days",
                        "etaMinutes": 36060
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/links": {
      "get": {
        "operationId": "inspectLink",
        "summary": "Inspect a link",
        "description": "What a link points to (platform, profile/post/video/…) and every service that can grow it. Start here when you have a link.",
        "tags": [
          "Catalog"
        ],
        "security": [],
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "Any link, e.g. https://x.com/yourname.",
            "schema": {
              "type": "string"
            },
            "example": "https://x.com/yourname"
          }
        ],
        "responses": {
          "200": {
            "description": "The link and the services that fit it.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "link": {
                      "$ref": "#/components/schemas/LinkInfo"
                    },
                    "services": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Service"
                      }
                    }
                  }
                },
                "example": {
                  "link": {
                    "url": "https://x.com/yourname",
                    "host": "x.com",
                    "platform": "x",
                    "target": "profile",
                    "label": "@yourname"
                  },
                  "services": [
                    {
                      "id": 12,
                      "platform": "x",
                      "platformLabel": "X",
                      "target": "profile",
                      "metric": "followers",
                      "metricLabel": "Followers",
                      "tier": "standard",
                      "name": "X Followers — Standard",
                      "description": "Real-looking accounts, steady delivery, 30-day refill.",
                      "linkHint": "https://x.com/yourname",
                      "minQty": 100,
                      "maxQty": 50000,
                      "pricePer1k": "4.99",
                      "pricePer1kMicros": "4990000",
                      "refillDays": 30,
                      "refillable": true,
                      "cancelable": true,
                      "startTime": "0–2 h",
                      "speed": "2K / day",
                      "tags": [
                        "refill"
                      ],
                      "startEstimate": "Usually starts within 1 h",
                      "delivery": {
                        "startMinutes": 60,
                        "perDay": 2000,
                        "avgMinutesPer1k": null
                      },
                      "packages": [
                        {
                          "quantity": 100,
                          "price": "0.50",
                          "eta": "~3 h",
                          "etaMinutes": 132
                        },
                        {
                          "quantity": 500,
                          "price": "2.50",
                          "eta": "~7 h",
                          "etaMinutes": 420
                        },
                        {
                          "quantity": 1000,
                          "price": "4.99",
                          "eta": "~13 h",
                          "etaMinutes": 780
                        },
                        {
                          "quantity": 5000,
                          "price": "24.95",
                          "eta": "~3 days",
                          "etaMinutes": 3660
                        },
                        {
                          "quantity": 50000,
                          "price": "249.50",
                          "eta": "~25 days",
                          "etaMinutes": 36060
                        }
                      ]
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Not a link.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "bad_link",
                    "message": "That does not look like a link."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/quotes": {
      "post": {
        "operationId": "createQuote",
        "summary": "Get a quote",
        "description": "The exact price of a quantity. Nothing is charged and no auth is needed.",
        "tags": [
          "Catalog"
        ],
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "service",
                  "quantity"
                ],
                "properties": {
                  "service": {
                    "type": "integer"
                  },
                  "quantity": {
                    "type": "integer"
                  },
                  "link": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "service": 12,
                "quantity": 1000
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The price.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "quote": {
                      "$ref": "#/components/schemas/Quote"
                    }
                  }
                },
                "example": {
                  "quote": {
                    "service": 12,
                    "quantity": 1000,
                    "pricePer1k": "4.99",
                    "total": "4.99",
                    "currency": "USD"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Quantity outside the range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "bad_quantity",
                    "message": "Quantity must be between 100 and 50,000.",
                    "details": {
                      "min": 100,
                      "max": 50000
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown or paused service.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "service_unavailable",
                    "message": "This service is not available right now."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/orders": {
      "get": {
        "operationId": "listOrders",
        "summary": "List orders",
        "description": "Your orders, newest first. Page with `before` = the smallest order number you have.",
        "tags": [
          "Orders"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "Filter by status.",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "processing",
                "completed",
                "partial",
                "refunded",
                "cancelled",
                "failed"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "1–200, default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "before",
            "in": "query",
            "description": "Only orders with a smaller number.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Orders.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "orders": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Order"
                      }
                    }
                  }
                },
                "example": {
                  "orders": [
                    {
                      "id": 1042,
                      "service": {
                        "id": 12,
                        "name": "X Followers — Standard",
                        "platform": "x",
                        "metric": "followers"
                      },
                      "link": "https://x.com/yourname",
                      "quantity": 1000,
                      "charge": "4.99",
                      "refunded": "0.00",
                      "status": "processing",
                      "startCount": 1520,
                      "delivered": 300,
                      "remains": 700,
                      "refillable": false,
                      "cancelable": true,
                      "source": "api",
                      "createdAt": "2026-10-16T12:00:00.000Z",
                      "finishedAt": null,
                      "expectedAt": "2026-10-17T01:00:00.000Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "operationId": "createOrder",
        "summary": "Place an order",
        "description": "Charges your balance and starts delivery. Send an `Idempotency-Key` header so a retry never double-charges. With `dry_run: true` nothing is charged: you get the price, your balance and whether it is enough.",
        "tags": [
          "Orders"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "service",
                  "link",
                  "quantity"
                ],
                "properties": {
                  "service": {
                    "type": "integer"
                  },
                  "link": {
                    "type": "string"
                  },
                  "quantity": {
                    "type": "integer"
                  },
                  "dry_run": {
                    "type": "boolean",
                    "default": false
                  },
                  "details": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Done-for-you services only: the answers to the service’s `form` (key → text; image fields → upload id)."
                  }
                }
              },
              "example": {
                "service": 12,
                "link": "https://x.com/yourname",
                "quantity": 1000
              },
              "examples": {
                "order": {
                  "summary": "Place an order",
                  "value": {
                    "service": 12,
                    "link": "https://x.com/yourname",
                    "quantity": 1000
                  }
                },
                "dryRun": {
                  "summary": "Dry run (no charge)",
                  "value": {
                    "service": 12,
                    "link": "https://x.com/yourname",
                    "quantity": 1000,
                    "dry_run": true
                  }
                },
                "doneForYou": {
                  "summary": "A done-for-you listing (upload the images first)",
                  "value": {
                    "service": 90,
                    "link": "https://dexscreener.com/robinhood/0x6e12a4c7b0f1d1e9e5b8c2d3a4f5e6d7c8b95eba",
                    "quantity": 1,
                    "details": {
                      "logo": "cm2uploadlogo0000000000000",
                      "banner": "cm2uploadbanner000000000000",
                      "website": "https://example.com",
                      "x": "https://x.com/yourtoken",
                      "contact": "@yourhandle"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Dry run answer — or a replay of an earlier order with the same Idempotency-Key (`replayed: true`).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "dry_run": {
                      "const": true
                    },
                    "quote": {
                      "$ref": "#/components/schemas/Quote"
                    },
                    "balance": {
                      "type": "string",
                      "pattern": "^\\d+\\.\\d{2,4}$",
                      "description": "Your balance. USD as a decimal string."
                    },
                    "sufficient": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "dry_run": true,
                  "quote": {
                    "service": 12,
                    "quantity": 1000,
                    "total": "4.99",
                    "currency": "USD"
                  },
                  "balance": "12.00",
                  "sufficient": true
                }
              }
            }
          },
          "201": {
            "description": "Placed and charged.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "order": {
                      "$ref": "#/components/schemas/Order"
                    },
                    "replayed": {
                      "type": "boolean"
                    },
                    "charged": {
                      "type": "string",
                      "pattern": "^\\d+\\.\\d{2,4}$",
                      "description": "Charged. USD as a decimal string."
                    }
                  }
                },
                "example": {
                  "order": {
                    "id": 1042,
                    "service": {
                      "id": 12,
                      "name": "X Followers — Standard",
                      "platform": "x",
                      "metric": "followers"
                    },
                    "link": "https://x.com/yourname",
                    "quantity": 1000,
                    "charge": "4.99",
                    "refunded": "0.00",
                    "status": "pending",
                    "startCount": null,
                    "delivered": null,
                    "remains": null,
                    "refillable": false,
                    "cancelable": true,
                    "source": "api",
                    "createdAt": "2026-10-16T12:00:00.000Z",
                    "finishedAt": null,
                    "expectedAt": "2026-10-17T01:00:00.000Z"
                  },
                  "replayed": false,
                  "charged": "4.99"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/orders/{id}": {
      "get": {
        "operationId": "getOrder",
        "summary": "Get an order",
        "description": "Status and progress of one order.",
        "tags": [
          "Orders"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderNumber"
          }
        ],
        "responses": {
          "200": {
            "description": "The order.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "order": {
                      "$ref": "#/components/schemas/Order"
                    }
                  }
                },
                "example": {
                  "order": {
                    "id": 1042,
                    "service": {
                      "id": 12,
                      "name": "X Followers — Standard",
                      "platform": "x",
                      "metric": "followers"
                    },
                    "link": "https://x.com/yourname",
                    "quantity": 1000,
                    "charge": "4.99",
                    "refunded": "0.00",
                    "status": "processing",
                    "startCount": 1520,
                    "delivered": 300,
                    "remains": 700,
                    "refillable": false,
                    "cancelable": true,
                    "source": "api",
                    "createdAt": "2026-10-16T12:00:00.000Z",
                    "finishedAt": null,
                    "expectedAt": "2026-10-17T01:00:00.000Z"
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/orders/{id}/refill": {
      "post": {
        "operationId": "refillOrder",
        "summary": "Request a refill",
        "description": "For a completed order of a refillable service whose count dropped. Carried out in the background.",
        "tags": [
          "Orders"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderNumber"
          }
        ],
        "responses": {
          "202": {
            "description": "Requested.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActionRequested"
                },
                "example": {
                  "ok": true,
                  "order": 1042,
                  "action": "refill",
                  "status": "requested"
                }
              }
            }
          },
          "400": {
            "description": "Not refillable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_refillable",
                    "message": "This order cannot be refilled."
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/orders/{id}/cancel": {
      "post": {
        "operationId": "cancelOrder",
        "summary": "Request a cancel",
        "description": "For a pending or processing order of a cancelable service. Whatever was not delivered is refunded to your balance.",
        "tags": [
          "Orders"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderNumber"
          }
        ],
        "responses": {
          "202": {
            "description": "Requested.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActionRequested"
                },
                "example": {
                  "ok": true,
                  "order": 1042,
                  "action": "cancel",
                  "status": "requested"
                }
              }
            }
          },
          "400": {
            "description": "Not cancelable now.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_cancelable",
                    "message": "This order cannot be cancelled now."
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/uploads": {
      "post": {
        "operationId": "createUpload",
        "summary": "Upload an image",
        "description": "An image for a done-for-you order (logo, banner): multipart field `file`, or the raw bytes with an image Content-Type. PNG, JPG, WEBP or GIF up to 4 MB. Send the returned `id` in the order’s `details`; an upload no order uses is deleted after a day.",
        "tags": [
          "Orders"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              },
              "example": {
                "file": "(the image file)"
              }
            },
            "image/png": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Stored.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "upload": {
                      "$ref": "#/components/schemas/Upload"
                    }
                  }
                },
                "example": {
                  "upload": {
                    "id": "cm2uploadlogo0000000000000",
                    "mime": "image/png",
                    "size": 48213,
                    "width": 512,
                    "height": 512
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/balance": {
      "get": {
        "operationId": "getBalance",
        "summary": "Get balance",
        "description": "Your spendable balance in USD.",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "Balance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Balance"
                },
                "example": {
                  "balance": "12.00",
                  "currency": "USD"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/v1/deposits/methods": {
      "get": {
        "operationId": "listDepositMethods",
        "summary": "Deposit methods",
        "description": "How to top up: your own deposit address per asset (USDG on Robinhood Chain; the project token at 10 % off once live).",
        "tags": [
          "Deposits"
        ],
        "responses": {
          "200": {
            "description": "Methods.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "methods": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/DepositMethod"
                      }
                    }
                  }
                },
                "example": {
                  "methods": [
                    {
                      "id": "usdg",
                      "asset": "USDG",
                      "chain": {
                        "id": 4663,
                        "name": "Robinhood Chain",
                        "explorer": "https://rh-scan.com"
                      },
                      "tokenAddress": "0x0000000000000000000000000000000000000001",
                      "decimals": 6,
                      "address": "0x1111111111111111111111111111111111111111",
                      "treasury": "0x2222222222222222222222222222222222222222",
                      "minimum": "1.00",
                      "discountPct": 0,
                      "priceUsd": null,
                      "note": "Send any amount of USDG on Robinhood Chain to your address; it is credited 1 USDG = $1."
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/v1/deposits": {
      "get": {
        "operationId": "listDeposits",
        "summary": "List deposits",
        "description": "Your deposits, newest first.",
        "tags": [
          "Deposits"
        ],
        "responses": {
          "200": {
            "description": "Deposits.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deposits": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Deposit"
                      }
                    }
                  }
                },
                "example": {
                  "deposits": [
                    {
                      "id": "cmkd3p0s1t0000qrs",
                      "asset": "USDG",
                      "amount": "25.00",
                      "value": "25.00",
                      "credit": "25.00",
                      "txHash": "0xabababababababababababababababababababababababababababababababab",
                      "status": "credited",
                      "createdAt": "2026-10-16T11:58:00.000Z",
                      "creditedAt": "2026-10-16T11:58:20.000Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/v1/deposits/claim": {
      "post": {
        "operationId": "claimDeposit",
        "summary": "Claim a wallet payment",
        "description": "After paying the treasury from a wallet, send the transaction hash: it is verified on chain and credited.",
        "tags": [
          "Deposits"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "txHash"
                ],
                "properties": {
                  "txHash": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "txHash": "0xabababababababababababababababababababababababababababababababab"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Credited.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deposit": {
                      "$ref": "#/components/schemas/Deposit"
                    }
                  }
                },
                "example": {
                  "deposit": {
                    "id": "cmkd3p0s1t0000qrs",
                    "asset": "USDG",
                    "amount": "25.00",
                    "value": "25.00",
                    "credit": "25.00",
                    "txHash": "0xabababababababababababababababababababababababababababababababab",
                    "status": "credited",
                    "createdAt": "2026-10-16T11:58:00.000Z",
                    "creditedAt": "2026-10-16T11:58:20.000Z"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/v1/keys": {
      "get": {
        "operationId": "listApiKeys",
        "summary": "List API keys",
        "description": "Every key of the signed-in user, revoked ones included. Secrets are never shown again.",
        "tags": [
          "API keys"
        ],
        "security": [
          {
            "session": []
          }
        ],
        "x-session-only": true,
        "responses": {
          "200": {
            "description": "Keys.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "keys": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ApiKey"
                      }
                    }
                  }
                },
                "example": {
                  "keys": [
                    {
                      "id": "cmk1a2b3c0000xyz",
                      "name": "Growth agent",
                      "prefix": "fimi_live_Ab3x",
                      "scopes": [
                        "read",
                        "write"
                      ],
                      "dailyCap": "50.00",
                      "perOrderCap": "10.00",
                      "platforms": [
                        "x",
                        "tiktok"
                      ],
                      "lastUsedAt": null,
                      "createdAt": "2026-10-16T12:00:00.000Z",
                      "revokedAt": null
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Sent with an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "session_required",
                    "message": "API keys and webhooks are managed from your signed-in Spoofy dashboard, not with an API key."
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createApiKey",
        "summary": "Create an API key",
        "description": "Every field is optional. `scopes: [\"read\"]` makes a read-only key. Caps are USD strings; `platforms` limits which platforms the key may order for. The full key is in this answer only — store it now. Up to 20 active keys.",
        "tags": [
          "API keys"
        ],
        "security": [
          {
            "session": []
          }
        ],
        "x-session-only": true,
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "read",
                        "write"
                      ]
                    },
                    "default": [
                      "read",
                      "write"
                    ]
                  },
                  "dailyCap": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "perOrderCap": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "platforms": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              },
              "example": {
                "name": "Growth agent",
                "scopes": [
                  "read",
                  "write"
                ],
                "dailyCap": "50.00",
                "perOrderCap": "10.00",
                "platforms": [
                  "x",
                  "tiktok"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created. `key` is shown once.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "key": {
                      "type": "string"
                    },
                    "apiKey": {
                      "$ref": "#/components/schemas/ApiKey"
                    }
                  }
                },
                "example": {
                  "key": "fimi_live_Ab3x…(48 chars)",
                  "apiKey": {
                    "id": "cmk1a2b3c0000xyz",
                    "name": "Growth agent",
                    "prefix": "fimi_live_Ab3x",
                    "scopes": [
                      "read",
                      "write"
                    ],
                    "dailyCap": "50.00",
                    "perOrderCap": "10.00",
                    "platforms": [
                      "x",
                      "tiktok"
                    ],
                    "lastUsedAt": null,
                    "createdAt": "2026-10-16T12:00:00.000Z",
                    "revokedAt": null
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/api/v1/keys/{id}": {
      "delete": {
        "operationId": "revokeApiKey",
        "summary": "Revoke an API key",
        "description": "The key stops working at once.",
        "tags": [
          "API keys"
        ],
        "security": [
          {
            "session": []
          }
        ],
        "x-session-only": true,
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "cmk1a2b3c0000xyz"
          }
        ],
        "responses": {
          "200": {
            "description": "Revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "const": true
                    }
                  }
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/webhooks": {
      "get": {
        "operationId": "listWebhooks",
        "summary": "List webhooks",
        "description": "Your active webhook endpoints.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "session": []
          }
        ],
        "x-session-only": true,
        "responses": {
          "200": {
            "description": "Webhooks.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "webhooks": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Webhook"
                      }
                    }
                  }
                },
                "example": {
                  "webhooks": [
                    {
                      "id": "cmk9w8v7u0000abc",
                      "url": "https://example.com/spoofy-webhook",
                      "events": [
                        "order.updated"
                      ],
                      "active": true,
                      "createdAt": "2026-10-16T12:00:00.000Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "operationId": "createWebhook",
        "summary": "Add a webhook",
        "description": "Public https URL; no `events` means every event. The signing `secret` is in this answer only. Up to 10 webhooks.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "session": []
          }
        ],
        "x-session-only": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "order.updated",
                        "deposit.credited",
                        "balance.low"
                      ]
                    }
                  }
                }
              },
              "example": {
                "url": "https://example.com/spoofy-webhook",
                "events": [
                  "order.updated"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "webhook": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  }
                },
                "example": {
                  "webhook": {
                    "id": "cmk9w8v7u0000abc",
                    "url": "https://example.com/spoofy-webhook",
                    "events": [
                      "order.updated"
                    ],
                    "active": true,
                    "createdAt": "2026-10-16T12:00:00.000Z",
                    "secret": "whsec_…(shown once)"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad URL.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "bad_webhook_url",
                    "message": "Webhook URLs must use https://."
                  }
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/api/v1/webhooks/{id}": {
      "delete": {
        "operationId": "deleteWebhook",
        "summary": "Remove a webhook",
        "description": "Stops delivery to this endpoint; queued deliveries are dropped.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "session": []
          }
        ],
        "x-session-only": true,
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Webhook id.",
            "schema": {
              "type": "string"
            },
            "example": "cmk9w8v7u0000abc"
          }
        ],
        "responses": {
          "200": {
            "description": "Removed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "const": true
                    }
                  }
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/openapi.json": {
      "get": {
        "operationId": "getOpenApi",
        "summary": "This document",
        "description": "The OpenAPI 3.1 description of the API, for code generators and agents.",
        "tags": [
          "Meta"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "OpenAPI 3.1 JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2": {
      "post": {
        "operationId": "smmCompatible",
        "summary": "SMM-compatible endpoint",
        "description": "The SMM-standard API: form-encoded (or JSON, or query string) `key` + `action`. Answers follow the SMM v2 shapes; errors are `{\"error\": \"…\"}` with HTTP 200, as SMM tools expect. The key is the same Spoofy API key with the same caps.",
        "tags": [
          "SMM-compatible"
        ],
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/SmmRequest"
              },
              "example": {
                "key": "fimi_live_…",
                "action": "add",
                "service": 12,
                "link": "https://x.com/yourname",
                "quantity": 1000
              },
              "examples": {
                "services": {
                  "summary": "action=services",
                  "value": {
                    "key": "fimi_live_…",
                    "action": "services"
                  }
                },
                "add": {
                  "summary": "action=add",
                  "value": {
                    "key": "fimi_live_…",
                    "action": "add",
                    "service": 12,
                    "link": "https://x.com/yourname",
                    "quantity": 1000
                  }
                },
                "status": {
                  "summary": "action=status",
                  "value": {
                    "key": "fimi_live_…",
                    "action": "status",
                    "order": 1042
                  }
                },
                "balance": {
                  "summary": "action=balance",
                  "value": {
                    "key": "fimi_live_…",
                    "action": "balance"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Depends on `action`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": [
                    "object",
                    "array"
                  ]
                },
                "examples": {
                  "services": {
                    "summary": "services",
                    "value": [
                      {
                        "service": 12,
                        "name": "X Followers — Standard",
                        "type": "Default",
                        "category": "X · Followers",
                        "rate": "4.99",
                        "min": 100,
                        "max": 50000,
                        "refill": true,
                        "cancel": true
                      }
                    ]
                  },
                  "add": {
                    "summary": "add",
                    "value": {
                      "order": 1042
                    }
                  },
                  "status": {
                    "summary": "status",
                    "value": {
                      "charge": "4.99",
                      "start_count": "1520",
                      "status": "In progress",
                      "remains": "700",
                      "currency": "USD"
                    }
                  },
                  "balance": {
                    "summary": "balance",
                    "value": {
                      "balance": "12.00",
                      "currency": "USD"
                    }
                  },
                  "error": {
                    "summary": "error",
                    "value": {
                      "error": "Your balance is $1.00 and this order costs $4.99. Top up $3.99 to place it."
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "order.updated": {
      "post": {
        "operationId": "webhook_order_updated",
        "summary": "order.updated",
        "description": "An order changed status or progress. Signed with `Fimi-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, \"<t>.<body>\")>`. Answer 2xx within 10 s; anything else is retried with backoff for about 24 h.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              },
              "example": {
                "id": "evt_cmk5e6f7g0000hij",
                "type": "order.updated",
                "created": 1792152000,
                "data": {
                  "order": {
                    "id": 1042,
                    "service": {
                      "id": 12,
                      "name": "X Followers — Standard",
                      "platform": "x",
                      "metric": "followers"
                    },
                    "link": "https://x.com/yourname",
                    "quantity": 1000,
                    "charge": "4.99",
                    "refunded": "0.00",
                    "status": "processing",
                    "startCount": 1520,
                    "delivered": 300,
                    "remains": 700,
                    "refillable": false,
                    "cancelable": true,
                    "source": "api",
                    "createdAt": "2026-10-16T12:00:00.000Z",
                    "finishedAt": null,
                    "expectedAt": "2026-10-17T01:00:00.000Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received."
          }
        }
      }
    },
    "deposit.credited": {
      "post": {
        "operationId": "webhook_deposit_credited",
        "summary": "deposit.credited",
        "description": "A deposit was credited to the balance. Signed with `Fimi-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, \"<t>.<body>\")>`. Answer 2xx within 10 s; anything else is retried with backoff for about 24 h.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              },
              "example": {
                "id": "evt_cmk5e6f7g0000hij",
                "type": "deposit.credited",
                "created": 1792152000,
                "data": {
                  "deposit": {
                    "id": "cmkd3p0s1t0000qrs",
                    "asset": "USDG",
                    "amount": "25.00",
                    "value": "25.00",
                    "credit": "25.00",
                    "txHash": "0xabababababababababababababababababababababababababababababababab",
                    "status": "credited",
                    "createdAt": "2026-10-16T11:58:00.000Z",
                    "creditedAt": "2026-10-16T11:58:20.000Z"
                  },
                  "balance": "37.00"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received."
          }
        }
      }
    },
    "balance.low": {
      "post": {
        "operationId": "webhook_balance_low",
        "summary": "balance.low",
        "description": "Your balance is running low. Signed with `Fimi-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, \"<t>.<body>\")>`. Answer 2xx within 10 s; anything else is retried with backoff for about 24 h.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              },
              "example": {
                "id": "evt_cmk5e6f7g0000hij",
                "type": "balance.low",
                "created": 1792152000,
                "data": {
                  "balance": "1.20",
                  "currency": "USD"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "fimi_live_…",
        "description": "Create keys at https://spoofy.social/app/developers. Send `Authorization: Bearer fimi_live_…`."
      },
      "session": {
        "type": "apiKey",
        "in": "cookie",
        "name": "better-auth.session_token",
        "description": "The signed-in browser session (the Spoofy web app itself)."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable machine code (see the error table).",
                "examples": [
                  "insufficient_balance"
                ]
              },
              "message": {
                "type": "string",
                "description": "Plain-English explanation, safe to show a person."
              },
              "details": {
                "type": "object",
                "additionalProperties": true,
                "description": "Extra fields for some codes, e.g. `shortfall`."
              }
            }
          }
        }
      },
      "Service": {
        "type": "object",
        "description": "Something you can buy: one metric on one platform at one quality tier.",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Service id — pass it as `service` when quoting or ordering."
          },
          "platform": {
            "type": "string",
            "examples": [
              "x",
              "tiktok",
              "telegram",
              "youtube",
              "dexscreener",
              "web"
            ]
          },
          "platformLabel": {
            "type": "string"
          },
          "target": {
            "type": "string",
            "enum": [
              "profile",
              "post",
              "video",
              "channel",
              "group",
              "token",
              "site",
              "track",
              "stream",
              "server"
            ],
            "description": "What kind of link it takes."
          },
          "metric": {
            "type": "string",
            "examples": [
              "followers",
              "likes",
              "views",
              "members",
              "reactions",
              "visits"
            ]
          },
          "metricLabel": {
            "type": "string"
          },
          "tier": {
            "type": "string",
            "examples": [
              "basic",
              "standard",
              "premium"
            ]
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "linkHint": {
            "type": "string",
            "description": "An example of the link this service takes."
          },
          "minQty": {
            "type": "integer"
          },
          "maxQty": {
            "type": "integer"
          },
          "kind": {
            "type": "string",
            "enum": [
              "count",
              "time",
              "manual"
            ],
            "description": "`count`: units delivered (followers, views…). `time`: live viewers for `minutes` — `quantity` is how many at most; stopping early refunds the minutes that did not run. `manual`: done-for-you work (a listing), one per order, with a form to fill in (`form`)."
          },
          "minutes": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Time-based services: how long one order runs."
          },
          "linkPlatforms": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Link platforms it takes besides its own (\"*\" = any link)."
          },
          "form": {
            "type": [
              "array",
              "null"
            ],
            "description": "Done-for-you services: what to send as `details` when ordering. Image fields take an upload id (POST /api/v1/uploads).",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string",
                  "examples": [
                    "logo",
                    "banner",
                    "description",
                    "website",
                    "x",
                    "telegram",
                    "discord",
                    "contact"
                  ]
                },
                "kind": {
                  "type": "string",
                  "enum": [
                    "image",
                    "text",
                    "textarea",
                    "url",
                    "email"
                  ]
                },
                "label": {
                  "type": "string"
                },
                "required": {
                  "type": "boolean"
                },
                "hint": {
                  "type": "string"
                },
                "max": {
                  "type": "integer",
                  "description": "Text: at most this many characters."
                },
                "image": {
                  "type": "object",
                  "properties": {
                    "minWidth": {
                      "type": "integer"
                    },
                    "minHeight": {
                      "type": "integer"
                    },
                    "ratio": {
                      "type": "number",
                      "description": "Width ÷ height (1 = square)."
                    },
                    "maxBytes": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "pricePer1k": {
            "type": "string",
            "pattern": "^\\d+\\.\\d{2,4}$",
            "description": "Price per 1,000 units. USD as a decimal string."
          },
          "pricePer1kMicros": {
            "type": "string",
            "description": "Same price in micro-USD (1 USD = 1,000,000), as a string."
          },
          "pricePerUnit": {
            "type": "string",
            "description": "Price of one unit (one viewer for `minutes`, one listing), USD."
          },
          "refillDays": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Days a drop is refilled for, when refillable."
          },
          "refillable": {
            "type": "boolean"
          },
          "cancelable": {
            "type": "boolean"
          },
          "startTime": {
            "type": [
              "string",
              "null"
            ]
          },
          "speed": {
            "type": [
              "string",
              "null"
            ]
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "startEstimate": {
            "type": [
              "string",
              "null"
            ],
            "description": "When delivery usually starts, in words (\"Usually starts within 1 h\"); null until there is an estimate."
          },
          "delivery": {
            "type": [
              "object",
              "null"
            ],
            "description": "The delivery estimate as numbers, to work out the time for any quantity: minutes = startMinutes + quantity ÷ perDay × 1440; without a speed, avgMinutesPer1k × max(1, quantity ÷ 1000). Null until there is an estimate.",
            "properties": {
              "startMinutes": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Typical wait before delivery starts."
              },
              "perDay": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Typical units delivered per day once started."
              },
              "avgMinutesPer1k": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Typical minutes for 1,000 units, used when the speed is unknown."
              }
            }
          },
          "packages": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "quantity": {
                  "type": "integer"
                },
                "price": {
                  "type": "string",
                  "pattern": "^\\d+\\.\\d{2,4}$",
                  "description": "Package total. USD as a decimal string."
                },
                "eta": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Estimated time until fully delivered, in words (\"~2 days\")."
                },
                "etaMinutes": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "The same estimate in minutes."
                }
              }
            }
          }
        }
      },
      "LinkInfo": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "host": {
            "type": "string"
          },
          "platform": {
            "type": "string"
          },
          "target": {
            "type": "string"
          },
          "label": {
            "type": "string",
            "description": "What we recognised, e.g. \"@yourname\" or \"Post\"."
          },
          "chain": {
            "type": "string",
            "description": "Token pages that name their chain (gmgn.ai/<chain>/token/…)."
          },
          "note": {
            "type": "string",
            "description": "Set when we recognise the link but cannot grow it yet (e.g. a GMGN token on a chain we do not serve), saying why."
          }
        }
      },
      "Upload": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Send it in an order’s `details` for an image field."
          },
          "mime": {
            "type": "string",
            "enum": [
              "image/png",
              "image/jpeg",
              "image/webp",
              "image/gif"
            ]
          },
          "size": {
            "type": "integer",
            "description": "Bytes."
          },
          "width": {
            "type": "integer"
          },
          "height": {
            "type": "integer"
          }
        }
      },
      "Quote": {
        "type": "object",
        "properties": {
          "service": {
            "type": "integer"
          },
          "quantity": {
            "type": "integer"
          },
          "pricePer1k": {
            "type": "string",
            "pattern": "^\\d+\\.\\d{2,4}$",
            "description": "Price per 1,000. USD as a decimal string."
          },
          "total": {
            "type": "string",
            "pattern": "^\\d+\\.\\d{2,4}$",
            "description": "What the order costs. USD as a decimal string."
          },
          "currency": {
            "const": "USD"
          }
        }
      },
      "Order": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Order number."
          },
          "service": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "name": {
                "type": "string"
              },
              "platform": {
                "type": "string"
              },
              "metric": {
                "type": "string"
              }
            }
          },
          "link": {
            "type": "string"
          },
          "quantity": {
            "type": "integer"
          },
          "charge": {
            "type": "string",
            "pattern": "^\\d+\\.\\d{2,4}$",
            "description": "Charged at placement. USD as a decimal string."
          },
          "refunded": {
            "type": "string",
            "pattern": "^\\d+\\.\\d{2,4}$",
            "description": "Refunded so far (partial deliveries and failures refund automatically). USD as a decimal string."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "processing",
              "completed",
              "partial",
              "refunded",
              "cancelled",
              "failed"
            ]
          },
          "kind": {
            "type": "string",
            "enum": [
              "count",
              "time",
              "manual"
            ],
            "description": "As the service’s `kind`."
          },
          "startCount": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Count on the target when delivery started."
          },
          "delivered": {
            "type": [
              "integer",
              "null"
            ]
          },
          "remains": {
            "type": [
              "integer",
              "null"
            ]
          },
          "run": {
            "type": [
              "object",
              "null"
            ],
            "description": "Time-based orders: minutes ordered, minutes run so far, and the peak live count reached (at most `quantity`).",
            "properties": {
              "minutes": {
                "type": "integer"
              },
              "servedMinutes": {
                "type": "integer"
              },
              "peak": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          },
          "stage": {
            "type": [
              "object",
              "null"
            ],
            "description": "Done-for-you orders: where the work is. `step`: queued, submitted (with the platform, waiting for their review), approved, rejected (refunded in full), cancelled or failed.",
            "properties": {
              "step": {
                "type": "string"
              },
              "label": {
                "type": "string",
                "description": "The step in words."
              },
              "note": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          },
          "refillable": {
            "type": "boolean",
            "description": "A refill can be requested now."
          },
          "cancelable": {
            "type": "boolean",
            "description": "A cancel can be requested now."
          },
          "source": {
            "type": "string",
            "enum": [
              "web",
              "api",
              "v2",
              "mcp"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "finishedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "expectedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When we expect it fully delivered (estimate made when the order was placed); null when there is no estimate."
          }
        }
      },
      "ActionRequested": {
        "type": "object",
        "properties": {
          "ok": {
            "const": true
          },
          "order": {
            "type": "integer"
          },
          "action": {
            "type": "string",
            "enum": [
              "refill",
              "cancel"
            ]
          },
          "status": {
            "const": "requested"
          }
        }
      },
      "Balance": {
        "type": "object",
        "properties": {
          "balance": {
            "type": "string",
            "pattern": "^\\d+\\.\\d{2,4}$",
            "description": "Spendable balance. USD as a decimal string."
          },
          "currency": {
            "const": "USD"
          }
        }
      },
      "DepositMethod": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "enum": [
              "usdg",
              "token"
            ]
          },
          "asset": {
            "type": "string"
          },
          "chain": {
            "type": "object",
            "properties": {
              "id": {
                "const": 4663
              },
              "name": {
                "type": "string"
              },
              "explorer": {
                "type": "string"
              }
            }
          },
          "tokenAddress": {
            "type": "string"
          },
          "decimals": {
            "type": "integer"
          },
          "address": {
            "type": "string",
            "description": "Your own deposit address: send any amount, any time."
          },
          "treasury": {
            "type": [
              "string",
              "null"
            ],
            "description": "Treasury address (null until configured). Prefer sending to your own `address`: it is credited automatically, nothing to claim."
          },
          "minimum": {
            "type": "string",
            "pattern": "^\\d+\\.\\d{2,4}$",
            "description": "Smallest deposit credited. USD as a decimal string."
          },
          "discountPct": {
            "type": "number"
          },
          "priceUsd": {
            "type": [
              "string",
              "null"
            ]
          },
          "note": {
            "type": "string"
          }
        }
      },
      "Deposit": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "asset": {
            "type": "string"
          },
          "amount": {
            "type": "string"
          },
          "value": {
            "type": "string",
            "pattern": "^\\d+\\.\\d{2,4}$",
            "description": "Value at deposit time. USD as a decimal string."
          },
          "credit": {
            "type": "string",
            "pattern": "^\\d+\\.\\d{2,4}$",
            "description": "Credited to balance. USD as a decimal string."
          },
          "txHash": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "seen",
              "credited"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "creditedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "ApiKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "prefix": {
            "type": "string",
            "description": "First characters of the key, to tell keys apart."
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "read",
                "write"
              ]
            }
          },
          "dailyCap": {
            "type": [
              "string",
              "null"
            ],
            "description": "Max USD spent per UTC day (net of refunds); null = no cap."
          },
          "perOrderCap": {
            "type": [
              "string",
              "null"
            ],
            "description": "Max USD per order; null = no cap."
          },
          "platforms": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Allowed platforms; empty = all."
          },
          "lastUsedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "revokedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "order.updated",
                "deposit.credited",
                "balance.low"
              ]
            },
            "description": "Empty = every event."
          },
          "active": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "secret": {
            "type": "string",
            "description": "Signing secret `whsec_…` — in the create answer only."
          }
        }
      },
      "WebhookEvent": {
        "type": "object",
        "required": [
          "id",
          "type",
          "created",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Event id; also in the Fimi-Event-Id header. Use it to drop duplicates."
          },
          "type": {
            "type": "string",
            "enum": [
              "order.updated",
              "deposit.credited",
              "balance.low"
            ]
          },
          "created": {
            "type": "integer",
            "description": "Unix seconds."
          },
          "data": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "SmmRequest": {
        "type": "object",
        "required": [
          "key",
          "action"
        ],
        "properties": {
          "key": {
            "type": "string",
            "description": "Your Spoofy API key (fimi_live_…)."
          },
          "action": {
            "type": "string",
            "enum": [
              "services",
              "add",
              "status",
              "refill",
              "cancel",
              "balance"
            ]
          },
          "service": {
            "type": "integer",
            "description": "add: service id."
          },
          "link": {
            "type": "string",
            "description": "add: the link to grow."
          },
          "quantity": {
            "type": "integer",
            "description": "add: how many."
          },
          "order": {
            "type": "integer",
            "description": "status / refill / cancel: one order number."
          },
          "orders": {
            "type": "string",
            "description": "status / refill / cancel: up to 100 order numbers, comma separated."
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "The request is not valid. `error.message` says why.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "invalid_body",
                "message": "Send {\"service\": <id>, \"link\": \"<url>\", \"quantity\": <n>}."
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "No valid API key or session.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "invalid_api_key",
                "message": "The API key is missing, revoked or wrong."
              }
            }
          }
        }
      },
      "PaymentRequired": {
        "description": "Balance too low for this order.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "insufficient_balance",
                "message": "Your balance is $1.00 and this order costs $4.99. Top up $3.99 to place it.",
                "details": {
                  "balance": "1.00",
                  "required": "4.99",
                  "shortfall": "3.99"
                }
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "Refused by this key's safety rails (scope, platforms, caps) or session-only.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "over_order_cap",
                "message": "This order costs $24.95, above this key's per-order limit of $10.00."
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "Not found on your account.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "not_found",
                "message": "Order not found."
              }
            }
          }
        }
      },
      "Conflict": {
        "description": "A limit was reached.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "too_many_keys",
                "message": "You already have 20 active keys. Revoke one you no longer use first."
              }
            }
          }
        }
      },
      "Internal": {
        "description": "Our side failed. Safe to retry.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "internal",
                "message": "Something went wrong on our side. Try again in a moment."
              }
            }
          }
        }
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "description": "Any unique string (≤ 120 chars) per intended order. Retrying with the same key returns the first order instead of charging twice.",
        "schema": {
          "type": "string",
          "maxLength": 120
        },
        "example": "b6f1c0de-9a4e-4c55-8a1e-5f7c2d9e1a01"
      },
      "OrderNumber": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Order number.",
        "schema": {
          "type": "integer"
        },
        "example": 1042
      }
    }
  },
  "x-error-codes": [
    {
      "code": "invalid_body",
      "status": 400,
      "meaning": "The JSON body is missing or has the wrong shape. The message says what to send."
    },
    {
      "code": "bad_link",
      "status": 400,
      "meaning": "The link is not a URL we can read. Send the full address, e.g. https://x.com/yourname."
    },
    {
      "code": "wrong_platform",
      "status": 400,
      "meaning": "The service is for another platform than the link (e.g. a TikTok service with an X link)."
    },
    {
      "code": "bad_quantity",
      "status": 400,
      "meaning": "Quantity outside the service range. `details.min` / `details.max` hold the range."
    },
    {
      "code": "not_refillable",
      "status": 400,
      "meaning": "This order cannot be refilled (service has no refill, or the order is not completed)."
    },
    {
      "code": "not_cancelable",
      "status": 400,
      "meaning": "This order cannot be cancelled now."
    },
    {
      "code": "chain_not_supported",
      "status": 400,
      "meaning": "The token is on a chain this service does not serve yet (GMGN live viewers: Robinhood Chain only)."
    },
    {
      "code": "details_required",
      "status": 400,
      "meaning": "A done-for-you service needs a field of its `form`. `details.field` names it."
    },
    {
      "code": "bad_details",
      "status": 400,
      "meaning": "A `details` answer is not right (not a link, too long, an unknown or unsuitable upload). `details.field` names it."
    },
    {
      "code": "no_file",
      "status": 400,
      "meaning": "The upload carried no file."
    },
    {
      "code": "bad_webhook_url",
      "status": 400,
      "meaning": "Webhook URL must be public https://."
    },
    {
      "code": "unauthorized",
      "status": 401,
      "meaning": "No API key and no session. Send Authorization: Bearer fimi_live_…."
    },
    {
      "code": "invalid_api_key",
      "status": 401,
      "meaning": "The API key is wrong or revoked."
    },
    {
      "code": "insufficient_balance",
      "status": 402,
      "meaning": "Balance too low. `details.shortfall` is the USD amount to top up."
    },
    {
      "code": "read_only_key",
      "status": 403,
      "meaning": "This key has the read scope only and cannot place, refill or cancel orders."
    },
    {
      "code": "platform_not_allowed",
      "status": 403,
      "meaning": "The service's platform is not on this key's allow-list."
    },
    {
      "code": "over_order_cap",
      "status": 403,
      "meaning": "The order costs more than this key's per-order cap."
    },
    {
      "code": "over_daily_cap",
      "status": 403,
      "meaning": "The order would take this key over its daily spend cap (UTC day, net of refunds)."
    },
    {
      "code": "session_required",
      "status": 403,
      "meaning": "Keys and webhooks are managed from the signed-in dashboard; an API key cannot manage them."
    },
    {
      "code": "bad_origin",
      "status": 403,
      "meaning": "A browser request from another site was refused."
    },
    {
      "code": "not_found",
      "status": 404,
      "meaning": "No such order / key / webhook on your account."
    },
    {
      "code": "service_unavailable",
      "status": 404,
      "meaning": "The service id does not exist or is paused right now."
    },
    {
      "code": "too_many_keys",
      "status": 409,
      "meaning": "You already have 20 active keys. Revoke one first."
    },
    {
      "code": "too_many_webhooks",
      "status": 409,
      "meaning": "You already have 10 webhooks. Remove one first."
    },
    {
      "code": "link_busy",
      "status": 409,
      "meaning": "As many as this service allows are already running on that link (GMGN: 120 live viewers per token). `details.available` is how many more fit now."
    },
    {
      "code": "too_large",
      "status": 413,
      "meaning": "The upload is over 4 MB."
    },
    {
      "code": "not_an_image",
      "status": 415,
      "meaning": "The upload is not a PNG, JPG, WEBP or GIF image."
    },
    {
      "code": "too_many_uploads",
      "status": 429,
      "meaning": "Too many uploads in the last hour."
    },
    {
      "code": "internal",
      "status": 500,
      "meaning": "Something failed on our side. Safe to retry; writes with the same Idempotency-Key never double-charge."
    }
  ]
}