openapi: 3.1.0
info:
  title: Bespoke Labs API
  version: "1.0"
  description: >-
    The Bespoke Labs API serves Nimble, a family of models for text classification, routing,
    moderation, and other judgments about text or JSON. Ask up to 64 yes/no, multiple-choice,
    or rating questions in one request, and get a probability for every answer.
servers:
  - url: https://api.bespokelabs.ai
security:
  - bearerAuth: []
paths:
  /v1/systemone:
    post:
      summary: Ask questions
      description: >-
        Send a state and questions about it to Nimble. The model field picks the model.
        The path /v1/nimble/systemone takes the same requests.
      operationId: systemOne
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SystemOneRequest"
            examples:
              questions:
                summary: Questions (nimble-latest)
                value:
                  model: nimble-latest
                  state: The customer was charged twice and asks for a refund. The service still works.
                  questions:
                    refund:
                      type: noul
                      instructions: Does the customer request a refund?
                    department:
                      type: choice
                      instructions: Which department should handle this request?
                      criteria:
                        billing: Charges, payments and refunds
                        technical: Software bugs and outages
                    urgency:
                      type: score
                      instructions: How urgent is this request?
                      criteria:
                        - Routine billing request; service works
                        - Some functionality unavailable
                        - Complete service outage
      responses:
        "200":
          description: The answers, keyed by question ID.
          headers:
            x-request-id:
              $ref: "#/components/headers/RequestId"
            x-typesafe-request-id:
              $ref: "#/components/headers/TypesafeRequestId"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SystemOneResponse"
              examples:
                questions:
                  summary: Questions (nimble-latest)
                  value:
                    model: nimble-latest
                    answers:
                      refund:
                        type: noul
                        noul: 0.998
                      department:
                        type: choice
                        choice: billing
                        probabilities:
                          billing: 1.0
                          technical: 0.0
                        confidence: 1.0
                      urgency:
                        type: score
                        score: 0.0
                        legend:
                          "0": Routine billing request; service works
                          "1": Some functionality unavailable
                          "2": Complete service outage
                        probabilities:
                          "0": 1.0
                          "1": 0.0
                          "2": 0.0
                        confidence: 1.0
                    usage:
                      input_tokens: 338
                      output_tokens: 4
        "401":
          description: The API key is missing or not valid.
          headers:
            x-request-id:
              $ref: "#/components/headers/RequestId"
            x-typesafe-request-id:
              $ref: "#/components/headers/TypesafeRequestId"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "402":
          description: Your organization does not have enough credit for the request.
          headers:
            x-request-id:
              $ref: "#/components/headers/RequestId"
            x-typesafe-request-id:
              $ref: "#/components/headers/TypesafeRequestId"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "413":
          description: The request body is larger than 1 MiB.
          headers:
            x-request-id:
              $ref: "#/components/headers/RequestId"
            x-typesafe-request-id:
              $ref: "#/components/headers/TypesafeRequestId"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: The request is not valid, or it is above a limit. The detail field says why.
          headers:
            x-request-id:
              $ref: "#/components/headers/RequestId"
            x-typesafe-request-id:
              $ref: "#/components/headers/TypesafeRequestId"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "429":
          description: Your organization has reached its limit on concurrent requests, which is 4 until its first credit purchase and 100 after. Retry after the number of seconds in the Retry-After header.
          headers:
            x-request-id:
              $ref: "#/components/headers/RequestId"
            x-typesafe-request-id:
              $ref: "#/components/headers/TypesafeRequestId"
            Retry-After:
              $ref: "#/components/headers/RetryAfter"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "502":
          description: A model returned an error. Retry with backoff.
          headers:
            x-request-id:
              $ref: "#/components/headers/RequestId"
            x-typesafe-request-id:
              $ref: "#/components/headers/TypesafeRequestId"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: A model is starting, or Nimble is not available for a moment. Retry after the number of seconds in the Retry-After header. You are not charged.
          headers:
            x-request-id:
              $ref: "#/components/headers/RequestId"
            x-typesafe-request-id:
              $ref: "#/components/headers/TypesafeRequestId"
            Retry-After:
              $ref: "#/components/headers/RetryAfter"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "504":
          description: The request took too long.
          headers:
            x-request-id:
              $ref: "#/components/headers/RequestId"
            x-typesafe-request-id:
              $ref: "#/components/headers/TypesafeRequestId"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "529":
          description: The model is busy. Retry after about one second, with backoff.
          headers:
            x-request-id:
              $ref: "#/components/headers/RequestId"
            x-typesafe-request-id:
              $ref: "#/components/headers/TypesafeRequestId"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
components:
  headers:
    RequestId:
      description: The ID of this request. Send it to Bespoke Labs when you report a problem.
      schema:
        type: string
    TypesafeRequestId:
      description: The same ID as x-request-id. TypeSafe's SDK reads this header.
      schema:
        type: string
    RetryAfter:
      description: The number of seconds to wait before you retry.
      schema:
        type: integer
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: Your Bespoke Labs API key.
  schemas:
    SystemOneRequest:
      type: object
      description: Typed questions about text or JSON.
      required: [state, questions]
      properties:
        model:
          type: string
          enum:
            - nimble-latest
            - nimble-v4-max
            - nimble-v4
            - nimble-v3
          default: nimble-latest
          description: >-
            nimble-latest currently points to nimble-v4-max, and it will move to newer models as they are released.
            nimble-v4 is deprecated and points to nimble-v4-max. nimble-v3 is deprecated.
            The response repeats the model name from the request.
        state:
          description: The text or JSON to ask about. Nimble reads a JSON state as JSON text.
          oneOf:
            - type: string
            - type: object
            - type: array
        questions:
          type: object
          description: Your question IDs mapped to questions. The answers use the same IDs.
          minProperties: 1
          maxProperties: 64
          additionalProperties:
            $ref: "#/components/schemas/GeneralQuestion"
    GeneralQuestion:
      oneOf:
        - $ref: "#/components/schemas/NoulQuestion"
        - $ref: "#/components/schemas/ChoiceQuestion"
        - $ref: "#/components/schemas/ScoreQuestion"
      discriminator:
        propertyName: type
        mapping:
          noul: "#/components/schemas/NoulQuestion"
          choice: "#/components/schemas/ChoiceQuestion"
          score: "#/components/schemas/ScoreQuestion"
    NoulQuestion:
      type: object
      title: Noul
      description: Asks whether a statement is true.
      required: [type]
      properties:
        type:
          type: string
          const: noul
        instructions:
          type: string
          description: The statement or question.
        criteria:
          type: object
          description: What true and false mean. Optional.
          properties:
            "true":
              type: string
            "false":
              type: string
    ChoiceQuestion:
      type: object
      title: Choice
      description: Asks which option fits best.
      required: [type, criteria]
      properties:
        type:
          type: string
          const: choice
        instructions:
          type: string
          description: The question.
        criteria:
          type: object
          description: Option keys mapped to descriptions. If a description is null, Nimble reads the key instead.
          minProperties: 2
          maxProperties: 255
          additionalProperties:
            type: [string, "null"]
    ScoreQuestion:
      type: object
      title: Score
      description: Asks where the state falls on a scale.
      required: [type, criteria]
      properties:
        type:
          type: string
          const: score
        instructions:
          type: string
          description: The question.
        criteria:
          type: array
          description: The levels, from lowest to highest.
          minItems: 2
          maxItems: 255
          items:
            type: string
    SystemOneResponse:
      type: object
      required: [model, answers, usage]
      properties:
        model:
          type: string
          description: The model name from the request.
        answers:
          type: object
          description: Question IDs mapped to answers.
          additionalProperties:
            $ref: "#/components/schemas/Answer"
        usage:
          $ref: "#/components/schemas/Usage"
    Answer:
      oneOf:
        - $ref: "#/components/schemas/NoulAnswer"
        - $ref: "#/components/schemas/ChoiceAnswer"
        - $ref: "#/components/schemas/ScoreAnswer"
      discriminator:
        propertyName: type
        mapping:
          noul: "#/components/schemas/NoulAnswer"
          choice: "#/components/schemas/ChoiceAnswer"
          score: "#/components/schemas/ScoreAnswer"
    NoulAnswer:
      type: object
      title: Noul answer
      required: [type, noul]
      properties:
        type:
          type: string
          const: noul
        noul:
          type: number
          minimum: 0
          maximum: 1
          description: The probability that the statement is true.
    ChoiceAnswer:
      type: object
      title: Choice answer
      required: [type, choice, probabilities, confidence]
      properties:
        type:
          type: string
          const: choice
        choice:
          type: string
          description: The option with the highest probability.
        probabilities:
          type: object
          description: Every option's probability. They add up to 1.
          additionalProperties:
            type: number
        confidence:
          type: number
          description: 1 when one option has all the probability, 0 when every option is equally likely. It is not the chance that the answer is right.
    ScoreAnswer:
      type: object
      title: Score answer
      required: [type, score, legend, probabilities, confidence]
      properties:
        type:
          type: string
          const: score
        score:
          type: number
          description: The expected level, counting from 0. It can fall between two levels.
        legend:
          type: object
          description: Level numbers mapped to their text.
          additionalProperties:
            type: string
        probabilities:
          type: object
          description: Every level's probability, keyed by level number. They add up to 1.
          additionalProperties:
            type: number
        confidence:
          type: number
          description: 1 when one level has all the probability, 0 when every level is equally likely.
    Usage:
      type: object
      required: [input_tokens, output_tokens]
      properties:
        input_tokens:
          type: integer
          description: The input tokens that you pay for.
        output_tokens:
          type: integer
    Error:
      type: object
      required: [detail, request_id]
      properties:
        detail:
          description: Why the request failed.
        request_id:
          type: string
          description: The ID of this request, the same as the x-request-id header.
