Skip to main content
POST
/
v1
/
score
/
batch
Score multiple candidates
curl --request POST \
  --url https://embed.nova.dweet.com/v1/score/batch \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --header 'X-Tenant-Id: <x-tenant-id>' \
  --data '
{
  "jobId": "job-123",
  "candidates": [
    {
      "applicationId": "app-001",
      "candidate": {
        "resumeUrl": "https://storage.example.com/resumes/candidate-001.pdf?token=xyz"
      }
    },
    {
      "applicationId": "app-002",
      "candidate": {
        "resumeUrl": "https://storage.example.com/resumes/candidate-002.pdf?token=xyz"
      }
    }
  ]
}
'
{
"batchId": "batch_abc123def456",
"jobs": [
{
"applicationId": "app-001",
"scoringJobId": "sj_abc123",
"status": "queued"
},
{
"applicationId": "app-002",
"scoringJobId": "sj_def456",
"status": "queued"
}
],
"totalQueued": 2,
"estimatedCompletionSeconds": 60
}
Submit multiple candidates for scoring in a single request. All candidates must be for the same job.

When to Use

Bulk Import

Importing historical applications into Nova

Backfill

Scoring existing candidates after onboarding

Request

{
  "jobId": "job-123",
  "candidates": [
    {
      "applicationId": "app-001",
      "candidate": {
        "resumeUrl": "https://storage.example.com/resumes/001.pdf?token=xyz"
      }
    },
    {
      "applicationId": "app-002",
      "candidate": {
        "resumeUrl": "https://storage.example.com/resumes/002.pdf?token=xyz"
      }
    }
  ]
}

Limits

LimitValue
Candidates per batch1-100
Resume URL validity2+ hours recommended

Response

{
  "batchId": "batch_abc123def456",
  "jobs": [
    {
      "applicationId": "app-001",
      "scoringJobId": "sj_abc123",
      "status": "queued"
    },
    {
      "applicationId": "app-002",
      "scoringJobId": "sj_def456",
      "status": "queued"
    }
  ],
  "totalQueued": 2,
  "totalSkipped": 0,
  "estimatedCompletionSeconds": 60
}

Job Status Values

StatusDescription
queuedNew scoring job created
skippedAlready scored (idempotent)

Idempotency

By default, candidates already scored for this job are skipped:
{
  "batchId": "batch_xyz789",
  "jobs": [
    {
      "applicationId": "app-001",
      "scoringJobId": "sj_existing123",
      "status": "skipped"
    },
    {
      "applicationId": "app-003",
      "scoringJobId": "sj_new789",
      "status": "queued"
    }
  ],
  "totalQueued": 1,
  "totalSkipped": 1
}

Re-scoring

To re-score all candidates in the batch:
{
  "jobId": "job-123",
  "candidates": [...],
  "rescore": true
}
Re-scoring counts as additional billable scores. Each candidate with rescore: true creates a new scoring job.

Result Delivery

Results are delivered individually via webhook: Each webhook contains:
  • scoringJobId - Nova’s ID for this specific job
  • applicationId - Your application ID
  • result - The score and assessment

Per-Candidate Options

Override batch defaults for individual candidates:
{
  "jobId": "job-123",
  "language": "English",
  "candidates": [
    {
      "applicationId": "app-001",
      "candidate": { "resumeUrl": "..." }
    },
    {
      "applicationId": "app-002",
      "candidate": { "resumeUrl": "..." },
      "language": "German"
    }
  ]
}

Error Handling

If some candidates fail validation, the entire batch is rejected:
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request validation failed",
    "details": [
      {
        "field": "candidates[1].candidate.resumeUrl",
        "code": "INVALID_FORMAT",
        "message": "Must be a valid HTTPS URL"
      }
    ]
  }
}
Individual processing failures (e.g., resume fetch failed) are delivered via score.failed webhooks.

Best Practices

While you can submit 100 candidates per batch, smaller batches (20-50) are easier to manage and retry on failure.
Use URLs valid for 24+ hours to handle queue delays and retries.
Store the batchId and individual scoringJobId values to correlate with incoming webhooks.
Some candidates may fail while others succeed. Process score.failed webhooks to identify and retry failures.

Example: Backfill Script

async function backfillCandidates(jobId, applications) {
  // Process in batches of 50
  const batchSize = 50;

  for (let i = 0; i < applications.length; i += batchSize) {
    const batch = applications.slice(i, i + batchSize);

    const response = await fetch('https://embed.nova.dweet.com/v1/score/batch', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${apiKey}`,
        'X-Tenant-Id': tenantId,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        jobId,
        candidates: batch.map(app => ({
          applicationId: app.id,
          candidate: { resumeUrl: app.resumeUrl },
        })),
      }),
    });

    const result = await response.json();
    console.log(`Batch submitted: ${result.totalQueued} queued, ${result.totalSkipped} skipped`);

    // Brief pause between batches to avoid rate limits
    await sleep(1000);
  }
}

Authorizations

Authorization
string
header
required

API key authentication. Use your environment-specific API key (sk_test_* for sandbox, sk_live_* for production).

Headers

X-Tenant-Id
string
required

Your customer/tenant identifier. Used for data isolation and per-customer metrics. Tenants are created automatically on first request.

Body

application/json
jobId
string
required

Your job ID. Must have active criteria stored. All candidates in the batch are scored against this job's criteria.

candidates
object[]
required

Candidates to score (1-100 per batch)

Required array length: 1 - 100 elements
language
string
default:English

Default language for assessment output (can be overridden per candidate)

rescore
boolean
default:false

When true, bypasses idempotency for all candidates in the batch

Response

Batch accepted and queued

batchId
string
required

Unique identifier for this batch submission

jobs
object[]
required

Status of each candidate in the batch

totalQueued
integer
required

Number of new scoring jobs created

totalSkipped
integer

Number of candidates skipped due to idempotency (already scored)

estimatedCompletionSeconds
integer

Estimated time until all jobs complete