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

# Generate Criteria

> Create screening criteria from a job description using AI

<Note>
  **Creates a new version**: If this job already has active criteria, a new criteria version is created and becomes the active version. Historical scores retain the criteria version they were scored against.
</Note>

## When to Use

Generate criteria once per job posting, typically when the job is finalized. This endpoint:

* Analyzes the job description to identify key requirements
* Creates structured screening criteria with importance levels
* Stores the criteria server-side for automatic use during scoring

## With or Without Questions

<Tabs>
  <Tab title="With Clarification Answers">
    **Recommended for best results.** Requires a prior call to [Generate Clarification Questions](/embed-api/endpoints/question-sets).

    Clarification answers help calibrate:

    * Which skills are `MUST_HAVE` vs `NICE_TO_HAVE`
    * The target seniority level
    * Any context not captured in the job description
  </Tab>

  <Tab title="Without Answers">
    Generates criteria directly from the job description. Use this when:

    * You want a quick setup without the questions workflow
    * The job description is comprehensive and unambiguous
    * You'll refine criteria later using the criteria management endpoints
  </Tab>
</Tabs>

## Answer requirements

If you include `answers`, also include `questionSetId` and answer every question in the question set.

## Example request

<CodeGroup>
  ```typescript TypeScript SDK theme={null}
  import { Nova } from '@nova-sdk/api';

  const nova = new Nova({
    apiKey: process.env.NOVA_API_KEY!,
    tenantId: 'acme-corp',
  });

  const criteria = await nova.jobs.criteria.generate.create({
    jobId: 'job-123',
    body: {
      jobContext: {
        jobTitle: 'Senior Software Engineer',
        companyName: 'Acme Corp',
        jobDescription: 'We are looking for a Senior Software Engineer with 5+ years experience...',
      },
      questionSetId: 'cmlz26fn5003dwp61u6vmj4mc',
      answers: [
        { id: 'q1', value: 'Senior (5+ years)' },
        { id: 'q2', value: ['Go', 'Kubernetes'] },
      ],
    },
  });
  ```

  ```bash cURL theme={null}
  curl -X POST 'https://embed.nova.dweet.com/v1/jobs/job-123/criteria/generate' \
    -H 'Authorization: Bearer sk_live_your_key' \
    -H 'X-Tenant-Id: acme-corp' \
    -H 'Content-Type: application/json' \
    -d '{
      "jobContext": {
        "jobTitle": "Senior Software Engineer",
        "companyName": "Acme Corp",
        "jobDescription": "We are looking for a Senior Software Engineer with 5+ years experience..."
      },
      "questionSetId": "cmlz26fn5003dwp61u6vmj4mc",
      "answers": [
        { "id": "q1", "value": "Senior (5+ years)" },
        { "id": "q2", "value": ["Go", "Kubernetes"] }
      ]
    }'
  ```
</CodeGroup>

## Example response

```json theme={null}
{
  "criteria": [
    {
      "id": "crit_a1b2c3d4e5f6",
      "text": "Strong proficiency in Go for backend development",
      "importance": "MUST_HAVE",
      "order": 0
    }
  ]
}
```

## Latency

**10-20 seconds** (synchronous)

The AI analyzes the job context to generate contextually relevant criteria. This is a one-time operation per job posting.

## Next Step

After generating criteria, you're ready to [Score Applications](/embed-api/endpoints/score). Nova loads the job's active criteria automatically.


## OpenAPI

````yaml POST /v1/jobs/{jobId}/criteria/generate
openapi: 3.1.0
info:
  title: Nova Embed API
  description: >-
    The Nova Embed API enables ATS platforms to generate job-scoped screening
    criteria and score applications asynchronously against those criteria.
  version: 1.0.0
  contact:
    name: Nova Support
    email: nova@dweet.com
servers:
  - url: https://embed.nova.dweet.com
    description: >-
      Environment is determined by API key prefix: sk_test_* for sandbox,
      sk_live_* for production.
security:
  - bearerAuth: []
tags:
  - name: Analytics
    description: View scoring performance, webhook health, and error breakdowns.
  - name: Criteria
    description: Generate and manage job-scoped screening criteria.
  - name: Scoring
    description: Submit applications for scoring and fetch scoring job results.
  - name: Deletion
    description: Request application or tenant deletion and poll for completion.
  - name: Criteria Library
    description: Manage tenant-scoped reusable criteria templates.
  - name: Rate Limits
    description: Check your current rate limit status.
  - name: Webhooks
    description: >-
      Events sent to your registered webhook endpoints. Verify signatures with
      HMAC-SHA256 using your webhook secret.
paths:
  /v1/jobs/{jobId}/criteria/generate:
    post:
      tags:
        - Criteria
      summary: Generate criteria
      description: >-
        Generate and store criteria for a job. Creates a new criteria version
        which becomes active.
      operationId: createCriteriaGeneration
      parameters:
        - $ref: '#/components/parameters/TenantId'
        - $ref: '#/components/parameters/JobId'
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GenerateCriteriaRequest'
      responses:
        '201':
          description: Created
          headers:
            X-RateLimit-Bucket:
              $ref: '#/components/headers/X-RateLimit-Bucket'
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            Idempotent-Replayed:
              $ref: '#/components/headers/Idempotent-Replayed'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenerateCriteriaResponse'
        '400':
          $ref: '#/components/responses/ErrorResponse'
        '401':
          $ref: '#/components/responses/ErrorResponse'
        '409':
          $ref: '#/components/responses/ErrorResponse'
        '422':
          $ref: '#/components/responses/ErrorResponse'
        '429':
          $ref: '#/components/responses/RateLimitedResponse'
        '500':
          $ref: '#/components/responses/ErrorResponse'
      x-codeSamples:
        - lang: typescript
          label: '@nova-sdk/api'
          source: |-
            import { Nova } from "@nova-sdk/api";

            const nova = new Nova({
              apiKey: "sk_test_...",
              tenantId: "acme-corp",
            });

            const result = await nova.jobs.criteria.generate.create({
              jobId: "job_abc123",
              body: {
                jobContext: {
                  jobTitle: "Senior Software Engineer",
                  companyName: "Acme Corp",
                  jobDescription: "We are looking for a senior engineer...",
                },
              },
            });
        - lang: bash
          label: cURL
          source: >-
            curl -X POST
            "https://embed.nova.dweet.com/v1/jobs/job_abc123/criteria/generate"
            \
              -H "Authorization: Bearer sk_test_..." \
              -H "X-Tenant-Id: acme-corp" \
              -H "Content-Type: application/json" \
              -d '{
              "jobContext": {
                "jobTitle": "Senior Software Engineer",
                "companyName": "Acme Corp",
                "jobDescription": "We are looking for a senior engineer..."
              }
            }'
components:
  parameters:
    TenantId:
      name: X-Tenant-Id
      in: header
      required: true
      description: Your customer identifier. Tenants are auto-provisioned on first request.
      schema:
        type: string
      example: acme-corp
    JobId:
      name: jobId
      in: path
      required: true
      description: Your job identifier (external ID).
      schema:
        type: string
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      description: >-
        Optional key that makes criteria and library mutation requests safe to
        retry without duplicating side effects. The namespace is shared across
        all API keys for the same partner and environment. Reuse the same key
        when retrying the same request parameters.
      schema:
        type: string
        minLength: 1
        maxLength: 255
      example: 2d6d8d5a-6c4f-4c2f-8c6e-5b6f0d51a1b2
  schemas:
    GenerateCriteriaRequest:
      type: object
      required:
        - jobContext
      additionalProperties: false
      properties:
        jobContext:
          $ref: '#/components/schemas/JobContext'
        questionSetId:
          type: string
          minLength: 1
        answers:
          type: array
          items:
            $ref: '#/components/schemas/QuestionAnswer'
      if:
        properties:
          answers:
            type: array
            minItems: 1
        required:
          - answers
      then:
        required:
          - jobContext
          - questionSetId
    GenerateCriteriaResponse:
      type: object
      required:
        - criteria
      properties:
        criteria:
          type: array
          items:
            $ref: '#/components/schemas/Criterion'
    JobContext:
      type: object
      properties:
        jobTitle:
          type: string
          minLength: 1
          maxLength: 500
        companyName:
          type: string
          minLength: 1
          maxLength: 500
        jobDescription:
          type: string
          minLength: 1
          maxLength: 50000
        additionalInfo:
          type: string
          maxLength: 50000
        applicationQuestions:
          maxItems: 50
          type: array
          items:
            type: object
            propertyNames:
              type: string
            additionalProperties: {}
        language:
          default: English
          type: string
          maxLength: 50
      required:
        - jobTitle
        - companyName
        - jobDescription
      additionalProperties: false
    QuestionAnswer:
      type: object
      required:
        - id
        - value
      properties:
        id:
          type: string
          minLength: 1
          maxLength: 100
          description: ID of the question being answered
        value:
          oneOf:
            - type: string
              maxLength: 10000
            - type: array
              maxItems: 50
              items:
                type: string
                maxLength: 10000
          description: >-
            Answer value. String for single-select questions, array of strings
            for multi-select.
    Criterion:
      type: object
      required:
        - id
        - text
        - importance
        - order
        - createdAt
      properties:
        id:
          type: string
        text:
          type: string
        importance:
          $ref: '#/components/schemas/CriterionImportance'
        order:
          type: integer
        createdAt:
          type: string
          format: date-time
    HttpError:
      type: object
      required:
        - type
        - code
        - status
        - message
        - retryable
        - traceId
      properties:
        type:
          type: string
          description: URI reference that identifies the error type
        code:
          $ref: '#/components/schemas/ErrorCode'
        status:
          type: integer
          description: HTTP status code
        message:
          type: string
          description: Error message
        retryable:
          type: boolean
          description: When true, retrying the request may succeed
        traceId:
          type: string
          description: Trace ID for debugging
        details:
          type:
            - array
            - 'null'
          description: Field-level validation details
          items:
            type: object
            required:
              - field
              - code
              - message
            properties:
              field:
                type: string
              code:
                type: string
              message:
                type: string
    CriterionImportance:
      type: string
      enum:
        - MUST_HAVE
        - PREFERRED
        - NICE_TO_HAVE
    ErrorCode:
      type: string
      description: >-
        Machine-readable error code. Generated from the canonical error
        registry.
      enum:
        - UNAUTHORIZED
        - FORBIDDEN
        - VALIDATION_ERROR
        - ANSWER_MISMATCH
        - CRITERIA_INVALID
        - CRITERIA_REVISION_CONFLICT
        - NOT_FOUND
        - TENANT_NOT_FOUND
        - JOB_NOT_FOUND
        - APPLICATION_NOT_FOUND
        - QUESTION_SET_NOT_FOUND
        - CRITERIA_NOT_FOUND
        - CRITERION_NOT_FOUND
        - CRITERIA_VERSION_NOT_FOUND
        - SCORING_JOB_NOT_FOUND
        - BATCH_NOT_FOUND
        - LIBRARY_CRITERION_NOT_FOUND
        - RATE_LIMITED
        - MONTHLY_TRIAL_QUOTA_EXCEEDED
        - IDEMPOTENCY_KEY_ALREADY_USED
        - IDEMPOTENCY_REQUEST_IN_PROGRESS
        - RESUME_FETCH_FAILED
        - RESUME_CONVERSION_FAILED
        - RESUME_ENCRYPTED
        - RESUME_CORRUPTED
        - RESUME_PARSE_FAILED
        - RESUME_TOO_LARGE
        - RESUME_EMPTY
        - RESUME_URL_BLOCKED
        - AI_PROCESSING_FAILED
        - AI_GENERATION_FAILED
        - AI_SCORING_FAILED
        - MISSING_JOB_DESCRIPTION
        - TIMEOUT
        - MAX_RETRIES_EXCEEDED
        - TASK_STUCK
        - DELETION_REQUEST_NOT_FOUND
        - DELETION_REQUEST_FAILED
        - INTERNAL_ERROR
        - SERVICE_UNAVAILABLE
        - UNKNOWN
  headers:
    X-RateLimit-Bucket:
      description: Which rate limit bucket the request was classified into
      schema:
        type: string
        enum:
          - criteria_ai
          - criteria_current_reads
          - scoring_intake_batch
          - scoring_intake_single
          - read_and_ops
          - rate_limit_status
          - analytics
    X-RateLimit-Limit:
      description: Maximum requests per second for this bucket
      schema:
        type: integer
    X-RateLimit-Remaining:
      description: Requests remaining in the current 1-second window
      schema:
        type: integer
    X-RateLimit-Reset:
      description: Unix timestamp when the current window resets
      schema:
        type: integer
    Idempotent-Replayed:
      description: >-
        Present and set to "true" when the response is replayed from the
        idempotency cache
      schema:
        type: string
        enum:
          - 'true'
    Retry-After:
      description: >-
        Seconds to wait before retrying a short-window RATE_LIMITED or
        service-unavailable response whose body has retryable: true.
      schema:
        type: integer
    X-RateLimit-Degraded:
      description: >-
        Present and set to "true" when rate limiting is operating in degraded
        mode (Redis unavailable). Values in other rate limit headers are
        best-effort estimates.
      schema:
        type: string
        enum:
          - 'true'
  responses:
    ErrorResponse:
      description: Error response
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/HttpError'
    RateLimitedResponse:
      description: >-
        Too many requests. Short-window RATE_LIMITED responses include retry
        timing and rate limit headers. Monthly trial quota responses use
        MONTHLY_TRIAL_QUOTA_EXCEEDED with retryable: false.
      headers:
        Retry-After:
          $ref: '#/components/headers/Retry-After'
        X-RateLimit-Bucket:
          $ref: '#/components/headers/X-RateLimit-Bucket'
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
        X-RateLimit-Degraded:
          $ref: '#/components/headers/X-RateLimit-Degraded'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/HttpError'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API key
      description: 'Use Authorization: Bearer sk_test_* or Authorization: Bearer sk_live_*.'

````