Skip to main content

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.

Error response format

Errors follow RFC 7807:
{
  "type": "https://docs.nova.dweet.com/embed-api/errors#validation-error",
  "code": "VALIDATION_ERROR",
  "status": 400,
  "message": "Request validation failed",
  "retryable": false,
  "traceId": "5c2f4f5b2c0a4ce0b6a31a1a18f8e9a1",
  "details": [
    {
      "field": "resume.url",
      "code": "invalid",
      "message": "Resume URL must be a valid URL"
    }
  ]
}
FieldDescription
typeRFC 7807 URI identifying the error category
codeMachine-readable error code for programmatic matching
statusHTTP status code
messageHuman-readable error description
retryableWhether retrying may succeed
traceIdTrace ID for debugging (also in X-Trace-Id header)
detailsField-level validation errors (when present)

When to retry

  • retryable: true: retry with exponential backoff
  • 429 RATE_LIMITED: wait for Retry-After header value
  • Other 4xx: fix the request first
For criteria and library mutations, use Idempotency-Key and reuse the same key on retries. Scoring submissions already deduplicate by jobId and applicationId.

Common error codes

CodeStatusAction
UNAUTHORIZED401Check API key and Authorization header
VALIDATION_ERROR400Fix the fields listed in details
ANSWER_MISMATCH400Answers must match the question set
CRITERIA_NOT_FOUND404Generate criteria for the job first
SCORING_JOB_NOT_FOUND404Verify scoringJobId exists for this tenant
RESUME_FETCH_FAILED422Check resume URL is accessible and not expired
RESUME_TOO_LARGE422File must be under 50 MB
RESUME_ENCRYPTED422Remove password protection
RESUME_CORRUPTED422Submit a corrected, complete resume file
RESUME_PARSE_FAILED422Confirm the file opens normally and contact support if it does
RATE_LIMITED429Wait for Retry-After and retry

Batch intake rejections

Batch scoring separates a valid batch envelope from invalid individual resume inputs. If at least one application can be accepted, POST /v1/jobs/{jobId}/scoring-batches returns 202 Accepted with acceptedApplications and rejectedApplications. Rejected applications do not create scoring jobs and do not emit score.failed webhooks. If every application is rejected before queueing, the endpoint returns 422 VALIDATION_ERROR. The details array contains one item per rejected application with the concrete public code, such as RESUME_CORRUPTED or RESUME_FETCH_FAILED.

Idempotency

These errors apply to routes that support the HTTP Idempotency-Key replay layer. Scoring submissions use built-in scoring idempotency instead. That means you won’t see IDEMPOTENCY_* errors on scoring submission or scoring batch endpoints just because you sent Idempotency-Key. Nova ignores the header there.
CodeStatusWhat to do
IDEMPOTENCY_REQUEST_IN_PROGRESS409Wait briefly and retry using the same Idempotency-Key
IDEMPOTENCY_KEY_ALREADY_USED422Do not retry. Generate a new key and retry only after you have fixed the request parameters
If a mutation reaches endpoint logic and returns a cacheable 4xx, retrying with the same Idempotency-Key replays that same error. If the request fails before endpoint logic runs, for example because a required header is missing, the Content-Type is invalid, the JSON is malformed, schema or param validation fails, or rate limiting blocks the request, the response is not cached.
This page covers the most common errors. For the complete list of error codes with HTTP status, retryability, and surfaces, see the Error Code Reference.

Error handling with the SDK

The TypeScript SDK retries automatically on 429 and 5xx errors with exponential backoff and Retry-After support. You only need to handle non-retryable errors:
import { Nova, NovaApiError } from '@nova-sdk/api';

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

try {
  const { scoringJob } = await nova.jobs.applications.scoringJobs.submit({
    jobId: 'job-123',
    applicationId: 'app-456',
    body: {
      resume: { type: 'url', url: 'https://storage.example.com/resumes/abc123.pdf' },
      jobDescription: 'We are looking for...',
    },
  });
} catch (err) {
  if (err instanceof NovaApiError) {
    console.log(err.code);      // e.g. 'VALIDATION_ERROR'
    console.log(err.status);    // e.g. 400
    console.log(err.retryable); // false
    console.log(err.traceId);   // for debugging
    console.log(err.details);   // field-level validation errors
  }
}
Disable retries if you want full control:
const nova = new Nova({
  apiKey: process.env.NOVA_API_KEY!,
  tenantId: 'acme-corp',
  retry: { maxRetries: 0 },
});

Manual retry logic (cURL / raw HTTP)

If you aren’t using the SDK, implement retries yourself:
async function novaRequest(url, { method, headers, body }) {
  const maxAttempts = 3;

  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    const response = await fetch(url, {
      method,
      headers,
      body: body ? JSON.stringify(body) : undefined,
    });

    if (response.ok) {
      return response.json();
    }

    const error = await response.json();

    if (response.status === 429) {
      const retryAfterSeconds = Number(response.headers.get("Retry-After") ?? "60");
      await new Promise((r) => setTimeout(r, retryAfterSeconds * 1000));
      continue;
    }

    if (error.retryable && attempt < maxAttempts) {
      const delayMs = 250 * Math.pow(2, attempt - 1);
      await new Promise((r) => setTimeout(r, delayMs));
      continue;
    }

    throw Object.assign(new Error(error.message), { error });
  }
}

Debugging

When contacting support, include the traceId, your timestamp and endpoint, and the HTTP status code.