@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" },
},
],
},
});curl -X POST "https://embed.nova.dweet.com/v1/jobs/job_abc123/scoring-batches" \
-H "Authorization: Bearer sk_test_..." \
-H "X-Tenant-Id: acme-corp" \
-H "Content-Type: application/json" \
-d '{
"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>",
"status": "pending",
"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": {
"code": "UNAUTHORIZED",
"message": "<string>",
"reason": "<string>"
}
}
]
}{
"type": "<string>",
"code": "UNAUTHORIZED",
"status": 123,
"message": "<string>",
"retryable": true,
"traceId": "<string>",
"details": [
{
"field": "<string>",
"code": "<string>",
"message": "<string>"
}
]
}{
"type": "<string>",
"code": "UNAUTHORIZED",
"status": 123,
"message": "<string>",
"retryable": true,
"traceId": "<string>",
"details": [
{
"field": "<string>",
"code": "<string>",
"message": "<string>"
}
]
}{
"type": "<string>",
"code": "UNAUTHORIZED",
"status": 123,
"message": "<string>",
"retryable": true,
"traceId": "<string>",
"details": [
{
"field": "<string>",
"code": "<string>",
"message": "<string>"
}
]
}{
"type": "<string>",
"code": "UNAUTHORIZED",
"status": 123,
"message": "<string>",
"retryable": true,
"traceId": "<string>",
"details": [
{
"field": "<string>",
"code": "<string>",
"message": "<string>"
}
]
}{
"type": "<string>",
"code": "UNAUTHORIZED",
"status": 123,
"message": "<string>",
"retryable": true,
"traceId": "<string>",
"details": [
{
"field": "<string>",
"code": "<string>",
"message": "<string>"
}
]
}{
"type": "<string>",
"code": "UNAUTHORIZED",
"status": 123,
"message": "<string>",
"retryable": true,
"traceId": "<string>",
"details": [
{
"field": "<string>",
"code": "<string>",
"message": "<string>"
}
]
}{
"type": "<string>",
"code": "UNAUTHORIZED",
"status": 123,
"message": "<string>",
"retryable": true,
"traceId": "<string>",
"details": [
{
"field": "<string>",
"code": "<string>",
"message": "<string>"
}
]
}API endpoints
Score Batch
Submit multiple applications for scoring in a single request
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" },
},
],
},
});curl -X POST "https://embed.nova.dweet.com/v1/jobs/job_abc123/scoring-batches" \
-H "Authorization: Bearer sk_test_..." \
-H "X-Tenant-Id: acme-corp" \
-H "Content-Type: application/json" \
-d '{
"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>",
"status": "pending",
"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": {
"code": "UNAUTHORIZED",
"message": "<string>",
"reason": "<string>"
}
}
]
}{
"type": "<string>",
"code": "UNAUTHORIZED",
"status": 123,
"message": "<string>",
"retryable": true,
"traceId": "<string>",
"details": [
{
"field": "<string>",
"code": "<string>",
"message": "<string>"
}
]
}{
"type": "<string>",
"code": "UNAUTHORIZED",
"status": 123,
"message": "<string>",
"retryable": true,
"traceId": "<string>",
"details": [
{
"field": "<string>",
"code": "<string>",
"message": "<string>"
}
]
}{
"type": "<string>",
"code": "UNAUTHORIZED",
"status": 123,
"message": "<string>",
"retryable": true,
"traceId": "<string>",
"details": [
{
"field": "<string>",
"code": "<string>",
"message": "<string>"
}
]
}{
"type": "<string>",
"code": "UNAUTHORIZED",
"status": 123,
"message": "<string>",
"retryable": true,
"traceId": "<string>",
"details": [
{
"field": "<string>",
"code": "<string>",
"message": "<string>"
}
]
}{
"type": "<string>",
"code": "UNAUTHORIZED",
"status": 123,
"message": "<string>",
"retryable": true,
"traceId": "<string>",
"details": [
{
"field": "<string>",
"code": "<string>",
"message": "<string>"
}
]
}{
"type": "<string>",
"code": "UNAUTHORIZED",
"status": 123,
"message": "<string>",
"retryable": true,
"traceId": "<string>",
"details": [
{
"field": "<string>",
"code": "<string>",
"message": "<string>"
}
]
}{
"type": "<string>",
"code": "UNAUTHORIZED",
"status": 123,
"message": "<string>",
"retryable": true,
"traceId": "<string>",
"details": [
{
"field": "<string>",
"code": "<string>",
"message": "<string>"
}
]
}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
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
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);
curl -X POST 'https://embed.nova.dweet.com/v1/jobs/job-123/scoring-batches' \
-H 'Authorization: Bearer sk_live_your_key' \
-H 'X-Tenant-Id: acme-corp' \
-H 'Content-Type: application/json' \
-d '{
"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.",
"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."
}
}
]
}'
Include
jobDescription at the batch level. It applies to all applications in the batch. See Data Retention for storage details.Idempotency
Re-submitting the samejobId 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.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 returns202 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
Use Authorization: Bearer sk_test_* or Authorization: Bearer sk_live_*.
Headers
Your customer identifier. Tenants are auto-provisioned on first request.
Path Parameters
Your job identifier (external ID).
Body
application/json
Was this page helpful?