Skip to main content
POST
/
v1
/
jobs
/
{jobId}
/
scoring-batches
@nova-sdk/api
import { Nova } from "@nova-sdk/api";

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

const result = await nova.jobs.scoringBatches.submit({
  jobId: "job_abc123",
  body: {
    jobDescription: "We are looking for a senior engineer...",
    applications: [
      {
        applicationId: "app_001",
        resume: { type: "url", url: "https://example.com/resumes/application-1.pdf" },
      },
      {
        applicationId: "app_002",
        resume: { type: "url", url: "https://example.com/resumes/application-2.pdf" },
      },
    ],
  },
});
{
  "batch": {
    "id": "<string>",
    "jobId": "<string>",
    "totalJobs": 123,
    "completedJobs": 123,
    "failedJobs": 123,
    "createdAt": "2023-11-07T05:31:56Z",
    "completedAt": "2023-11-07T05:31:56Z"
  },
  "scoringJobIds": [
    "<string>"
  ],
  "acceptedApplications": [
    {
      "applicationId": "<string>",
      "scoringJobId": "<string>"
    }
  ],
  "rejectedApplications": [
    {
      "applicationId": "<string>",
      "error": {
        "message": "<string>",
        "reason": "<string>"
      }
    }
  ]
}

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.

Submit multiple applications for scoring in a single request. Results are delivered individually via webhook. If some resume inputs are invalid, Nova accepts the valid applications and returns the invalid ones in rejectedApplications. Rejected applications are pre-queue intake rejections: no scoring job is created and no score.failed webhook is emitted for them.

Request

import { Nova } from '@nova-sdk/api';

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

const { batch, scoringJobIds, acceptedApplications, rejectedApplications } =
  await nova.jobs.scoringBatches.submit({
  jobId: 'job-123',
  body: {
    jobDescription: 'We are looking for a Senior Backend Engineer with 5+ years of experience in Node.js and TypeScript...',
    roleKnowledge: "Team values applicants who've built systems from scratch. Strong preference for distributed systems experience over frontend-heavy backgrounds.",
    applications: [
      {
        applicationId: 'app-001',
        resume: { type: 'url', url: 'https://storage.example.com/resumes/001.pdf' },
      },
      {
        applicationId: 'app-002',
        resume: { type: 'text', content: '# Jane Smith\n\nSenior Backend Engineer with 7 years of experience...' },
        applicationData: {
          applicationAnswers: [
            { question: 'Are you eligible to work in the UK?', answer: 'Yes' },
          ],
          context: 'Internal recruiter note: Strong referral from engineering lead. Applicant expressed interest in platform team specifically.',
        },
      },
    ],
  },
});

console.log(acceptedApplications);
console.log(rejectedApplications);
Include jobDescription at the batch level. It applies to all applications in the batch. See Data Retention for storage details.

Idempotency

Re-submitting the same jobId and set of applicationId values returns the existing batch.
This endpoint uses built-in batch scoring idempotency. Idempotency-Key is ignored here. To recover from a timeout or network uncertainty, re-submit the same batch for the same jobId. To create fresh scoring work for an application, use the single scoring endpoint with rescore.
If a previous submission rejected an application and you later fix that resume, re-submitting the exact same batch shape returns the original rejection. Submit the corrected application with a distinct batch shape or use the single scoring endpoint. The HTTP replay header Idempotent-Replayed: true never appears on this endpoint because batch scoring stays outside the generic Idempotency-Key middleware. See Idempotency for the full retry model.

Limits

  • 1 to 25 applications per request

Response

The API returns 202 Accepted.
{
  "batch": {
    "id": "cmlz26em4002cwp61t7ukh3lb",
    "jobId": "job-123",
    "status": "pending",
    "totalJobs": 2,
    "completedJobs": 0,
    "failedJobs": 0,
    "createdAt": "2025-12-14T10:30:45Z",
    "completedAt": null
  },
  "scoringJobIds": ["cmlz26dl3001bwp61r8sjf2ka", "cmlz26dl3001bwp61r8sjf2kb"],
  "acceptedApplications": [
    {
      "applicationId": "app-001",
      "scoringJobId": "cmlz26dl3001bwp61r8sjf2ka"
    },
    {
      "applicationId": "app-002",
      "scoringJobId": "cmlz26dl3001bwp61r8sjf2kb"
    }
  ],
  "rejectedApplications": []
}
totalJobs, completedJobs, and failedJobs count accepted applications only. Rejected applications are returned in deterministic applicationId order. If every application is rejected before queueing, the API returns 422 VALIDATION_ERROR with per-application details and does not create a batch.
{
  "code": "VALIDATION_ERROR",
  "status": 422,
  "message": "No applications could be accepted for scoring",
  "retryable": false,
  "details": [
    {
      "field": "applications[app-bad].resume",
      "code": "RESUME_CORRUPTED",
      "message": "Resume file appears to be corrupted"
    }
  ],
  "traceId": "trace_..."
}

Next step

Use Get Batch Status to poll batch progress if you need it.

Authorizations

Authorization
string
header
required

Use Authorization: Bearer sk_test_* or Authorization: Bearer sk_live_*.

Headers

X-Tenant-Id
string
required

Your customer identifier. Tenants are auto-provisioned on first request.

Path Parameters

jobId
string
required

Your job identifier (external ID).

Body

application/json
applications
object[]
required
Required array length: 1 - 25 elements
jobDescription
string
required
Required string length: 1 - 50000
jobTitle
string
Minimum string length: 1
companyName
string
Minimum string length: 1
roleKnowledge
string
Required string length: 1 - 15000

Response

Accepted

batch
object
required
scoringJobIds
string[]
required
acceptedApplications
object[]
required
rejectedApplications
object[]
required