openapi: 3.1.0
info:
  title: myProxyChecker API
  version: "1.0.0"
  description: Versioned IP lookup, JSON bulk proxy checking, account usage and API-key management.
  termsOfService: https://myproxychecker.com/acceptable-use
servers:
  - url: "https://myproxychecker.com"
tags:
  - name: Checks
  - name: Account
components:
  securitySchemes:
    ApiKeyHeader:
      type: apiKey
      in: header
      name: X-API-Key
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: mpc_live_...
  headers:
    RateLimitLimit:
      description: Daily account quota.
      schema: { type: integer }
    RateLimitRemaining:
      description: Units remaining before the UTC reset.
      schema: { type: integer }
    RateLimitReset:
      description: UTC reset time as a Unix timestamp.
      schema: { type: integer }
  schemas:
    Error:
      type: object
      required: [ok, error]
      additionalProperties: false
      properties:
        ok: { type: boolean, const: false }
        error:
          type: object
          required: [code, message]
          additionalProperties: false
          properties:
            code: { type: string }
            message: { type: string }
    ApiKeyRecord:
      type: object
      required: [id, accountId, keyPrefix, keyPreview, email, accountStatus, aupVersion, aupAcceptedAt, label, dailyLimit, usageToday, totalUsage, lastResetDate, isActive, createdAt]
      properties:
        id: { type: string, format: uuid }
        accountId: { type: string, format: uuid }
        keyPrefix: { type: string, enum: [mpc_live_, mpc_test_] }
        keyPreview: { type: string }
        email: { type: string, format: email, description: Unverified contact address; not an authentication factor. }
        accountStatus: { type: string, enum: [active, disabled] }
        aupVersion: { type: [string, "null"] }
        aupAcceptedAt: { type: [string, "null"], format: date-time }
        label: { type: string, maxLength: 80 }
        dailyLimit: { type: integer, minimum: 1 }
        usageToday: { type: integer, minimum: 0 }
        totalUsage: { type: integer, minimum: 0 }
        lastResetDate: { type: string, format: date }
        isActive: { type: boolean }
        createdAt: { type: string, format: date-time }
        lastUsedAt: { type: string, format: date-time }
        revokedAt: { type: string, format: date-time }
    UsageBucket:
      type: object
      required: [usedToday, dailyLimit, remaining, resetAt, lastResetDate, unit]
      properties:
        usedToday: { type: integer, minimum: 0 }
        dailyLimit: { type: integer, minimum: 1 }
        remaining: { type: integer, minimum: 0 }
        resetAt: { type: integer }
        lastResetDate: { type: string, format: date }
        unit: { type: string, enum: [lookups, proxies] }
        totalUsage: { type: integer, minimum: 0 }
    Usage:
      type: object
      required: [lookup, bulk]
      properties:
        lookup: { $ref: '#/components/schemas/UsageBucket' }
        bulk: { $ref: '#/components/schemas/UsageBucket' }
    ProxyCheckResult:
      type: object
      required: [raw, status, protocol, host, port, auth, connectIp, checkedAt]
      properties:
        raw: { type: string }
        status: { type: string, enum: [working, failed] }
        protocol: { type: [string, "null"], enum: [http, https, socks5, null] }
        host: { type: string }
        port: { type: integer, minimum: 1, maximum: 65535 }
        auth: { type: string, enum: [none, provided] }
        connectIp: { type: string }
        checkedAt: { type: string, format: date-time }
        error: { type: [object, "null"] }
        egress: { type: [object, "null"] }
        timings: { type: [object, "null"] }
        speedKbps: { type: [number, "null"] }
    BulkCheckRequest:
      type: object
      required: [proxies]
      additionalProperties: false
      properties:
        proxies:
          oneOf:
            - type: array
              minItems: 1
              maxItems: 64
              items: { type: string }
            - type: string
              minLength: 1
        protocol: { type: string, enum: [auto, http, https, socks5] }
  responses:
    BadRequest:
      description: The request body or a field is invalid.
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }
    Unauthorized:
      description: API key missing or invalid.
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }
    Forbidden:
      description: Account disabled or current AUP not accepted.
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }
    RateLimited:
      description: Caller or account quota exceeded.
      headers:
        X-RateLimit-Limit: { $ref: '#/components/headers/RateLimitLimit' }
        X-RateLimit-Remaining: { $ref: '#/components/headers/RateLimitRemaining' }
        X-RateLimit-Reset: { $ref: '#/components/headers/RateLimitReset' }
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }
paths:
  /v1/ip/{ip}:
    get:
      tags: [Checks]
      operationId: lookupIp
      summary: Look up one public IP.
      security:
        - ApiKeyHeader: []
        - BearerAuth: []
      parameters:
        - in: path
          name: ip
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Lookup response.
          headers:
            X-RateLimit-Limit: { $ref: '#/components/headers/RateLimitLimit' }
            X-RateLimit-Remaining: { $ref: '#/components/headers/RateLimitRemaining' }
            X-RateLimit-Reset: { $ref: '#/components/headers/RateLimitReset' }
          content:
            application/json:
              schema:
                type: object
                required: [ok]
                properties:
                  ok: { type: boolean, const: true }
                additionalProperties: true
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }
  /v1/check:
    post:
      tags: [Checks]
      operationId: checkProxies
      summary: Run a JSON bulk proxy check.
      security:
        - ApiKeyHeader: []
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/BulkCheckRequest' }
      responses:
        "200":
          description: Bulk JSON response.
          headers:
            X-RateLimit-Limit: { $ref: '#/components/headers/RateLimitLimit' }
            X-RateLimit-Remaining: { $ref: '#/components/headers/RateLimitRemaining' }
            X-RateLimit-Reset: { $ref: '#/components/headers/RateLimitReset' }
          content:
            application/json:
              schema:
                type: object
                required: [ok, meta, results, summary, usage]
                properties:
                  ok: { type: boolean, const: true }
                  meta: { type: object }
                  results:
                    type: array
                    items: { $ref: '#/components/schemas/ProxyCheckResult' }
                  summary: { type: object }
                  usage: { $ref: '#/components/schemas/Usage' }
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "413": { $ref: '#/components/responses/BadRequest' }
        "429": { $ref: '#/components/responses/RateLimited' }
        "503":
          description: Proxy checking is not configured.
  /v1/me:
    get:
      tags: [Account]
      operationId: getCurrentAccount
      summary: Return key metadata plus split lookup and bulk usage.
      security:
        - ApiKeyHeader: []
        - BearerAuth: []
      responses:
        "200":
          description: Key details.
          content:
            application/json:
              schema:
                type: object
                required: [ok, key, usage]
                properties:
                  ok: { type: boolean, const: true }
                  key: { $ref: '#/components/schemas/ApiKeyRecord' }
                  usage: { $ref: '#/components/schemas/Usage' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
  /api/v1/usage:
    get:
      tags: [Account]
      operationId: getUsage
      summary: Return split lookup and bulk usage only.
      security:
        - ApiKeyHeader: []
        - BearerAuth: []
      responses:
        "200":
          description: Usage response.
          content:
            application/json:
              schema:
                type: object
                required: [ok, usage]
                properties:
                  ok: { type: boolean, const: true }
                  usage: { $ref: '#/components/schemas/Usage' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
  /api/v1/keys:
    post:
      tags: [Account]
      operationId: createAccountKey
      summary: Create a developer API key.
      description: Creates a capability account. Email is unverified contact metadata, not an authentication factor.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email, acceptAup]
              additionalProperties: false
              properties:
                email: { type: string, format: email, maxLength: 254 }
                label: { type: string, maxLength: 80 }
                acceptAup: { type: boolean, const: true }
      responses:
        "201":
          description: Key created and shown once.
          content:
            application/json:
              schema:
                type: object
                required: [ok, key, record, warning]
                properties:
                  ok: { type: boolean, const: true }
                  key: { type: string, writeOnly: true }
                  record: { $ref: '#/components/schemas/ApiKeyRecord' }
                  warning: { type: string }
        "400": { $ref: '#/components/responses/BadRequest' }
        "429": { $ref: '#/components/responses/RateLimited' }
        "503":
          description: Self-service key signup is disabled.
    get:
      tags: [Account]
      operationId: listAccountKeys
      summary: List key metadata for the authenticated capability account.
      security:
        - ApiKeyHeader: []
        - BearerAuth: []
      responses:
        "200":
          description: Account key metadata.
          content:
            application/json:
              schema:
                type: object
                required: [ok, keys]
                properties:
                  ok: { type: boolean, const: true }
                  keys:
                    type: array
                    items: { $ref: '#/components/schemas/ApiKeyRecord' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
  /api/v1/keys/rotate:
    post:
      tags: [Account]
      operationId: rotateCurrentKey
      summary: Rotate the active API key.
      security:
        - ApiKeyHeader: []
        - BearerAuth: []
      responses:
        "200":
          description: New key returned once.
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
  /api/v1/keys/current:
    delete:
      tags: [Account]
      operationId: revokeCurrentKey
      summary: Revoke the active API key.
      security:
        - ApiKeyHeader: []
        - BearerAuth: []
      responses:
        "200":
          description: Key revoked.
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
