> ## Documentation Index
> Fetch the complete documentation index at: https://docs.compute.prentis.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Estimate a supervised fine-tuning job

> What the same request to create would cost, and whether it would be allowed to run -- without creating anything. The estimate shows its working (examples, tokens per example, epochs, rate) so you can tell whether the number is for the job you meant. An estimate is not the bill: you are billed for the tokens actually trained on.



## OpenAPI

````yaml openapi/prentis-training.openapi.yaml POST /accounts/{account}/supervisedFineTuningJobs:estimateCost
openapi: 3.1.0
info:
  title: Prentis Training API
  version: 0.1.0
  summary: >-
    Fine-tune models on your own data, with the same API key you use for
    inference.
  description: >
    Upload a dataset, start a fine-tuning job on it, and watch it train -- from
    code, with

    the API key you already use for inference. The jobs and datasets are the
    same ones the

    console shows: anything started here appears there, and the other way round.


    Every path is under `/v1/accounts/{account}`, where `{account}` is the
    account the key

    belongs to. A key reaches its own account only.


    A finished job produces a model in your account
    (`accounts/{account}/models/{outputModelId}`),

    listed under Custom models in the console. To call it, deploy it on a
    dedicated deployment

    and send inference requests to the deployment
    (`accounts/{account}/deployments/{deployment}`).
servers:
  - url: https://compute.prentis.ai/v1
    description: Production
security:
  - bearerAuth: []
tags:
  - name: training
  - name: datasets
paths:
  /accounts/{account}/supervisedFineTuningJobs:estimateCost:
    post:
      tags:
        - training
      summary: Estimate a supervised fine-tuning job
      description: >-
        What the same request to create would cost, and whether it would be
        allowed to run -- without creating anything. The estimate shows its
        working (examples, tokens per example, epochs, rate) so you can tell
        whether the number is for the job you meant. An estimate is not the
        bill: you are billed for the tokens actually trained on.
      operationId: estimateSupervisedFineTuningJobCost
      parameters:
        - $ref: '#/components/parameters/Account'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TrainingJobDraft'
      responses:
        '200':
          headers:
            x-request-id:
              $ref: '#/components/headers/x-request-id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EstimateCostResponse'
              example:
                estimate:
                  exampleCount: '4000'
                  avgTokensPerExample: '535'
                  epochs: 2
                  tokensProcessed: '4280000'
                  ratePerMillion:
                    amount: '0.45'
                    currency: USD
                  estimatedCost:
                    amount: '1.93'
                    currency: USD
                egress:
                  allowed: true
                  execution:
                    thirdParty: false
                  providerApproved: true
                  requiredAgreementVersion: v2
                  acceptedAgreementVersion: v2
          description: OK.
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '500':
          $ref: '#/components/responses/Error500'
        '503':
          $ref: '#/components/responses/Error503'
      x-codeSamples:
        - lang: curl
          label: cURL
          source: >-
            curl
            https://compute.prentis.ai/v1/accounts/my-account/supervisedFineTuningJobs:estimateCost
            \
              -H "Authorization: Bearer $PRENTIS_API_KEY" \
              -H "Content-Type: application/json" \
              -d '{
                "baseModel": "accounts/maas/models/your-base-model",
                "inputDatasetVersion": "accounts/my-account/datasets/support-chats",
                "config": { "outputModelId": "support-lora-v1", "epochs": 2 }
              }'
components:
  parameters:
    Account:
      name: account
      in: path
      required: true
      schema:
        type: string
        maxLength: 64
      description: >-
        Your account id -- the one in the console's address bar (my-account for
        this key). It must be the account the key belongs to.
  schemas:
    TrainingJobDraft:
      type: object
      required:
        - baseModel
        - inputDatasetVersion
        - config
      properties:
        baseModel:
          type: string
          maxLength: 256
          description: >-
            The model to fine-tune, as a full resource name
            (accounts/maas/models/your-base-model). Only base models offered for
            training are accepted -- the console's Training page lists them.


            The model to fine-tune, as a full resource name
            (accounts/maas/models/your-base-model). Only base models offered for
            training are accepted -- the console's Training page lists them.


            The model to fine-tune, as a full resource name
            (accounts/maas/models/your-base-model). Only base models offered for
            training are accepted -- the console's Training page lists them.


            The model to fine-tune, as a full resource name
            (accounts/maas/models/your-base-model). Only base models offered for
            training are accepted -- the console's Training page lists them.
        inputDatasetVersion:
          type: string
          maxLength: 256
          description: >-
            The training data: a dataset (accounts/{account}/datasets/{dataset})
            to use its latest version, or one version (…/versions/{n}) to pin
            it. The dataset must be READY.


            The preference data: a dataset to use its latest version, or one
            version to pin it. Each row needs a prompt and two answers -- see
            the dataset format guide. The dataset must be READY.


            The training data: a dataset (accounts/{account}/datasets/{dataset})
            to use its latest version, or one version (…/versions/{n}) to pin
            it. The dataset must be READY.


            The training data: a dataset (accounts/{account}/datasets/{dataset})
            to use its latest version, or one version (…/versions/{n}) to pin
            it. The dataset must be READY.
        evaluationDatasetVersion:
          type: string
          maxLength: 256
          description: >-
            Accepted so that the body of a create can be sent unchanged, but not
            used: the estimate covers the training data only.


            Optional held-out data to measure evaluation loss on, in the same
            form as inputDatasetVersion. Leave it empty and set
            config.evalAutoCarveoutBasisPoints to hold out a share of the
            training data instead, or leave both empty for no evaluation.


            Accepted so that the body of a create can be sent unchanged, but not
            used: the estimate covers the training data only.


            Optional held-out data to measure evaluation loss on, in the same
            form as inputDatasetVersion. Leave it empty and set
            config.evalAutoCarveoutBasisPoints to hold out a share of the
            training data instead, or leave both empty for no evaluation.
        config:
          $ref: '#/components/schemas/TrainingConfig'
          description: >-
            How to train. outputModelId is required: the id of the model the job
            will create, which must not already exist in your account. The rest
            are optional -- loraRank, learningRate (a string, e.g. "1e-4"),
            epochs (1-100), batchSize, maxContextLength (longer examples are
            skipped and counted, never truncated), earlyStop,
            evalAutoCarveoutBasisPoints (0-9999, in hundredths of a percent),
            lrSchedule (constant, cosine or linear_decay), warmupSteps, and
            dpoBeta (preference jobs only; a string, default "0.1"). Fixed once
            the job is created.


            How to train. outputModelId is required: the id of the model the job
            will create, which must not already exist in your account. The rest
            are optional -- loraRank, learningRate (a string, e.g. "1e-4"),
            epochs (1-100), batchSize, maxContextLength (longer examples are
            skipped and counted, never truncated), earlyStop,
            evalAutoCarveoutBasisPoints (0-9999, in hundredths of a percent),
            lrSchedule (constant, cosine or linear_decay), warmupSteps, and
            dpoBeta (preference jobs only; a string, default "0.1"). Fixed once
            the job is created.


            How to train. outputModelId is required: the id of the model the job
            will create, which must not already exist in your account. The rest
            are optional -- loraRank, learningRate (a string, e.g. "1e-4"),
            epochs (1-100), batchSize, maxContextLength (longer examples are
            skipped and counted, never truncated), earlyStop,
            evalAutoCarveoutBasisPoints (0-9999, in hundredths of a percent),
            lrSchedule (constant, cosine or linear_decay), warmupSteps, and
            dpoBeta (preference jobs only; a string, default "0.1"). Fixed once
            the job is created.


            How to train. outputModelId is required: the id of the model the job
            will create, which must not already exist in your account. The rest
            are optional -- loraRank, learningRate (a string, e.g. "1e-4"),
            epochs (1-100), batchSize, maxContextLength (longer examples are
            skipped and counted, never truncated), earlyStop,
            evalAutoCarveoutBasisPoints (0-9999, in hundredths of a percent),
            lrSchedule (constant, cosine or linear_decay), warmupSteps, and
            dpoBeta (preference jobs only; a string, default "0.1"). Fixed once
            the job is created.
    EstimateCostResponse:
      type: object
      properties:
        estimate:
          $ref: '#/components/schemas/TrainingEstimate'
        egress:
          $ref: '#/components/schemas/TrainingEgress'
    TrainingConfig:
      type: object
      required:
        - outputModelId
      properties:
        outputModelId:
          type: string
          maxLength: 64
        loraRank:
          type: integer
        learningRate:
          type: string
        epochs:
          type: integer
        batchSize:
          type: integer
        maxContextLength:
          type: integer
        earlyStop:
          type: boolean
        evalAutoCarveoutBasisPoints:
          type: integer
          minimum: 0
          maximum: 9999
        lrSchedule:
          type: string
        warmupSteps:
          type: integer
        dpoBeta:
          type: string
    TrainingEstimate:
      type: object
      properties:
        exampleCount:
          type: string
          format: int64
        avgTokensPerExample:
          type: string
          format: int64
        epochs:
          type: integer
        tokensProcessed:
          type: string
          format: int64
        ratePerMillion:
          allOf:
            - $ref: '#/components/schemas/Money'
        estimatedCost:
          $ref: '#/components/schemas/Money'
        rateMissing:
          type: boolean
    TrainingEgress:
      type: object
      properties:
        allowed:
          type: boolean
        refusalCode:
          type: string
          enum:
            - DATA_RESIDENCY_VIOLATION
            - AGREEMENT_REQUIRED
            - PROVIDER_NOT_ALLOWED
            - PROVIDER_SERVICE_UNAVAILABLE
        execution:
          $ref: '#/components/schemas/JobExecution'
        providerApproved:
          type: boolean
        requiredAgreementVersion:
          type: string
        acceptedAgreementVersion:
          type: string
        organizationResidency:
          type: string
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - message
            - type
            - code
          properties:
            message:
              type: string
            type:
              type: string
              enum:
                - invalid_request_error
                - authentication_error
                - permission_error
                - not_found_error
                - rate_limit_error
                - server_error
                - service_unavailable
                - billing_error
            code:
              type: string
              enum:
                - INVALID_REQUEST
                - INVALID_API_KEY
                - OPERATION_NOT_ALLOWED
                - TENANT_SUSPENDED
                - AGREEMENT_REQUIRED
                - DATA_RESIDENCY_VIOLATION
                - PROVIDER_NOT_ALLOWED
                - PROVIDER_SERVICE_UNAVAILABLE
                - INSUFFICIENT_BALANCE
                - PAYMENT_REQUIRED
                - MODEL_NOT_FOUND
                - MODEL_ALREADY_EXISTS
                - DATASET_NOT_FOUND
                - DATASET_ALREADY_EXISTS
                - DATASET_STATE_INVALID
                - DATASET_IN_USE
                - DATASET_TOO_LARGE
                - JSONL_LINE_NOT_OBJECT
                - JSONL_MISSING_FIELD
                - JSONL_ENCODING
                - JOB_NOT_FOUND
                - JOB_STATE_INVALID
                - TRAINING_RUN_ABANDONED
                - TRAINING_TOKENIZE_FAILED
                - TRAINING_BASE_NOT_EXPORTABLE
                - IDEMPOTENCY_CONFLICT
                - QUOTA_EXCEEDED
                - INTERNAL
                - STORAGE_UNAVAILABLE
            param:
              type:
                - string
                - 'null'
    Money:
      type: object
      properties:
        amount:
          type: string
        currency:
          type: string
    JobExecution:
      type: object
      properties:
        providerDisplayName:
          type: string
        thirdParty:
          type: boolean
  headers:
    x-request-id:
      schema:
        type: string
      required: true
      description: >-
        On every response, successes and errors alike. Quote it when you ask us
        about a call.
    Retry-After:
      schema:
        type: integer
        minimum: 0
      description: How many seconds to wait before retrying, on the responses that set it.
  responses:
    Error400:
      headers:
        x-request-id:
          $ref: '#/components/headers/x-request-id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
      description: >-
        `error.code` is one of: `DATASET_STATE_INVALID`, `INVALID_REQUEST`,
        `JSONL_ENCODING`, `JSONL_LINE_NOT_OBJECT`, `JSONL_MISSING_FIELD`,
        `TRAINING_BASE_NOT_EXPORTABLE`, `TRAINING_TOKENIZE_FAILED`. See the
        Errors page for what each one means, whether it is safe to retry, and
        whether it is billed.
    Error401:
      headers:
        x-request-id:
          $ref: '#/components/headers/x-request-id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
      description: >-
        `error.code` is one of: `INVALID_API_KEY`. See the Errors page for what
        each one means, whether it is safe to retry, and whether it is billed.
    Error403:
      headers:
        x-request-id:
          $ref: '#/components/headers/x-request-id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
      description: >-
        `error.code` is one of: `AGREEMENT_REQUIRED`,
        `DATA_RESIDENCY_VIOLATION`, `OPERATION_NOT_ALLOWED`,
        `PROVIDER_NOT_ALLOWED`, `PROVIDER_SERVICE_UNAVAILABLE`,
        `TENANT_SUSPENDED`. See the Errors page for what each one means, whether
        it is safe to retry, and whether it is billed.
    Error404:
      headers:
        x-request-id:
          $ref: '#/components/headers/x-request-id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
      description: >-
        `error.code` is one of: `DATASET_NOT_FOUND`, `JOB_NOT_FOUND`,
        `MODEL_NOT_FOUND`. See the Errors page for what each one means, whether
        it is safe to retry, and whether it is billed.
    Error500:
      headers:
        x-request-id:
          $ref: '#/components/headers/x-request-id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
      description: >-
        `error.code` is one of: `INTERNAL`, `TRAINING_RUN_ABANDONED`. See the
        Errors page for what each one means, whether it is safe to retry, and
        whether it is billed.
    Error503:
      headers:
        x-request-id:
          $ref: '#/components/headers/x-request-id'
        Retry-After:
          $ref: '#/components/headers/Retry-After'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
      description: >-
        `error.code` is one of: `STORAGE_UNAVAILABLE`. See the Errors page for
        what each one means, whether it is safe to retry, and whether it is
        billed.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        `Authorization: Bearer <your API key>` -- the same key as inference. A
        key reaches the account it belongs to and no other.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.