openapi: 3.1.0
info:
  title: Phylex Reseller API
  version: 1.1.0
  description: Tenant-scoped automation API for approved Phylex reseller workspaces. The default shared tenant quota is 1,200 read RPM and 300 write RPM and can be raised by staff per reseller. Inspect RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset on every response; a 429 also includes Retry-After.
  license:
    name: Proprietary
    url: https://phylex.net/terms
servers:
  - url: https://billing.phylex.net/api/proxy/reseller-api/v1
security:
  - bearerAuth: []
paths:
  /me:
    get:
      operationId: getResellerWorkspace
      summary: Read the reseller workspace
      x-required-scope: account:read
      responses:
        "200": { $ref: "#/components/responses/Success" }
        "401": { $ref: "#/components/responses/Error" }
        "403": { $ref: "#/components/responses/Error" }
  /plans:
    get:
      operationId: listResellerPlans
      summary: List the enabled reseller catalog
      x-required-scope: catalog:read
      responses:
        "200": { $ref: "#/components/responses/Success" }
        "401": { $ref: "#/components/responses/Error" }
        "403": { $ref: "#/components/responses/Error" }
  /customers:
    get:
      operationId: listResellerCustomers
      summary: List reseller customers
      x-required-scope: customers:read
      parameters:
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Offset"
      responses:
        "200": { $ref: "#/components/responses/Success" }
        "401": { $ref: "#/components/responses/Error" }
        "403": { $ref: "#/components/responses/Error" }
    post:
      operationId: createResellerCustomer
      summary: Create or link a reseller customer
      x-required-scope: customers:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CustomerCreate"
      responses:
        "200": { $ref: "#/components/responses/Success" }
        "201": { $ref: "#/components/responses/Success" }
        "400": { $ref: "#/components/responses/Error" }
        "409": { $ref: "#/components/responses/Error" }
  /customers/invite:
    post:
      operationId: inviteResellerCustomer
      summary: Send a customer invitation
      description: Use the stable customer_ref returned by customer creation or listing.
      x-required-scope: customers:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [customer_ref]
              properties:
                customer_ref:
                  $ref: "#/components/schemas/CustomerRef"
              additionalProperties: false
      responses:
        "200": { $ref: "#/components/responses/Success" }
        "400": { $ref: "#/components/responses/Error" }
        "404": { $ref: "#/components/responses/Error" }
  /tickets:
    get:
      operationId: listResellerTickets
      summary: Search reseller tickets
      x-required-scope: tickets:read
      parameters:
        - name: q
          in: query
          schema: { type: string, maxLength: 120 }
        - name: status
          in: query
          schema: { type: string, maxLength: 40 }
      responses:
        "200": { $ref: "#/components/responses/Success" }
        "401": { $ref: "#/components/responses/Error" }
        "403": { $ref: "#/components/responses/Error" }
    post:
      operationId: createResellerTicket
      summary: Open a reseller support ticket
      x-required-scope: tickets:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/TicketCreate"
      responses:
        "201": { $ref: "#/components/responses/Success" }
        "400": { $ref: "#/components/responses/Error" }
  /tickets/messages:
    parameters:
      - $ref: "#/components/parameters/TicketRef"
    get:
      operationId: listResellerTicketMessages
      summary: Read messages from an owned reseller ticket
      x-required-scope: tickets:read
      responses:
        "200": { $ref: "#/components/responses/Success" }
        "400": { $ref: "#/components/responses/Error" }
        "404": { $ref: "#/components/responses/Error" }
    post:
      operationId: createResellerTicketMessage
      summary: Reply to an owned reseller ticket
      x-required-scope: tickets:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [body]
              properties:
                body: { type: string, minLength: 1 }
              additionalProperties: false
      responses:
        "201": { $ref: "#/components/responses/Success" }
        "400": { $ref: "#/components/responses/Error" }
        "404": { $ref: "#/components/responses/Error" }
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: phxrk
      description: Reseller API key. Alternatively use X-Reseller-API-Key, but never send both headers.
  parameters:
    Limit:
      name: limit
      in: query
      schema: { type: integer, minimum: 1, maximum: 100, default: 50 }
    Offset:
      name: offset
      in: query
      schema: { type: integer, minimum: 0, default: 0 }
    TicketRef:
      name: ticket_ref
      in: query
      required: true
      schema:
        type: string
        pattern: "^PHX-RT-[0-9A-F]+$"
  schemas:
    CustomerRef:
      type: string
      pattern: "^PHX-RCU-[0-9A-F]+$"
    CustomerCreate:
      type: object
      required: [email]
      properties:
        email: { type: string, format: email }
        first_name: { type: string, maxLength: 120 }
        last_name: { type: string, maxLength: 120 }
        name: { type: string, maxLength: 240 }
        country_code: { type: string, pattern: "^[A-Za-z]{2}$" }
        external_ref: { type: string, maxLength: 128 }
      additionalProperties: false
    TicketCreate:
      type: object
      required: [subject]
      properties:
        subject: { type: string, minLength: 1 }
        body: { type: string }
        category_ref: { type: string, pattern: "^PHX-CAT-[0-9A-F]+$" }
        level: { type: string }
        service_type: { type: string }
      additionalProperties: false
    Error:
      type: object
      required: [error]
      properties:
        error: { type: string }
      additionalProperties: true
  responses:
    Success:
      description: Successful tenant-scoped response.
      content:
        application/json:
          schema:
            type: object
            additionalProperties: true
    Error:
      description: Stable machine-readable API error.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
