API KeysTasks

Tasks

Poll asynchronous operations and retrieve their final results using an API key.

Tasks

Many Notex APIs run asynchronously.

Instead of waiting for an operation to finish in the initial request, the create endpoint returns a task_id. Use the Tasks API to check progress and retrieve the final result.

Operations that commonly return a task include:

  • Note creation
  • Flashcards
  • Quiz
  • Mind map
  • Slides
  • Podcast
  • Shorts
  • Translation
Create content

Receive task_id

Poll the task

SUCCESS: use the result
FAILURE: handle the error

Base URL:

https://api.notexapp.com

Send the API key through X-API-Key:

-H "X-API-Key: ntx_live_..."

Poll a task result

GET /v1/create/tasks/{task_id}/result

Returns the current status and, when complete, the result of an asynchronous operation.

Path parameter

ParameterTypeRequiredDescription
task_idstringYesTask ID returned by a create endpoint

Example request

curl https://api.notexapp.com/v1/create/tasks/task_123456/result \
  -H "X-API-Key: ntx_live_..."

Replace task_123456 with the ID returned by the create request.

Task statuses

StatusMeaningRecommended action
PENDINGThe task is queuedContinue polling
PROCESSINGThe task is runningContinue polling
SUCCESSThe task completed successfullyRead data and stop polling
FAILUREThe task failedRead the error and stop polling
FAILThe task failedHandle it the same way as FAILURE

Support both FAILURE and FAIL.

Pending or processing

{
  "status": "PROCESSING",
  "step": "transcribing",
  "progress": 35,
  "estimated_time": 60
}
FieldTypeDescription
status"PENDING" | "PROCESSING"Current task status
stepstringCurrent processing step, when available
progressnumberEstimated progress from 0 to 100
estimated_timenumberEstimated remaining time in seconds

Progress fields are optional.

A minimal response may contain only:

{
  "status": "PROCESSING"
}

Successful result

{
  "status": "SUCCESS",
  "data": {
    "note_id": "665f...",
    "title": "Introduction to Machine Learning",
    "summary": "An overview of machine learning concepts..."
  }
}

Common result fields include:

FieldTypeDescription
data.note_idstringCreated or updated note ID
data.titlestringResult title
data.summarystringGenerated summary, when available
data.typestringType of generated content
data.audio_urlstringAudio URL for audio-producing operations
data.youtube_urlstringOriginal YouTube URL, when available
data.viewsstringView statistics, when available
messagestringAdditional API message

The structure of data depends on the task type. Do not assume that all tasks return the same fields.

Failed result

{
  "status": "FAILURE",
  "error": "Unsupported file format",
  "error_key": "unsupported_file_format",
  "message": "The uploaded file format is not supported."
}
FieldTypeDescription
status"FAILURE" | "FAIL"Failure status
errorstringShort error description
error_keystringStable machine-readable error code
messagestringMore detailed error message

When available, use error_key for application logic instead of comparing human-readable messages.

Polling guidance

SettingRecommendation
Polling intervalEvery 3–5 seconds
Stop conditionSUCCESS, FAILURE, or FAIL
TimeoutSet an application-level timeout appropriate for the task
CancellationSupport AbortSignal when possible

Do not:

  • Poll multiple times per second.
  • Continue polling after a terminal status.
  • Treat a client-side timeout as proof that the task failed.
  • Create a duplicate task immediately after a temporary network error.

A client timeout only means your application stopped waiting. The Notex task may still be running.

Bash polling example

TASK_ID="task_123456"

while true; do
  RESPONSE=$(curl -s \
    "https://api.notexapp.com/v1/create/tasks/$TASK_ID/result" \
    -H "X-API-Key: ntx_live_...")

  STATUS=$(echo "$RESPONSE" | jq -r '.status')

  if [ "$STATUS" = "SUCCESS" ]; then
    echo "$RESPONSE"
    break
  fi

  if [ "$STATUS" = "FAILURE" ] || [ "$STATUS" = "FAIL" ]; then
    echo "$RESPONSE" >&2
    exit 1
  fi

  sleep 5
done

JavaScript polling example

type TaskStatus =
  | 'PENDING'
  | 'PROCESSING'
  | 'SUCCESS'
  | 'FAILURE'
  | 'FAIL';

interface TaskProcessingResponse {
  status: 'PENDING' | 'PROCESSING';
  step?: string;
  progress?: number;
  estimated_time?: number;
}

interface TaskSuccessResponse<T> {
  status: 'SUCCESS';
  data: T;
  message?: string;
}

interface TaskFailureResponse {
  status: 'FAILURE' | 'FAIL';
  error?: string;
  error_key?: string;
  message?: string;
}

type TaskResultResponse<T> =
  | TaskProcessingResponse
  | TaskSuccessResponse<T>
  | TaskFailureResponse;

interface PollTaskOptions {
  intervalMs?: number;
  timeoutMs?: number;
  signal?: AbortSignal;
  onProgress?: (task: TaskProcessingResponse) => void;
}

async function pollTask<T>(
  taskId: string,
  apiKey: string,
  options: PollTaskOptions = {},
): Promise<T> {
  const {
    intervalMs = 4000,
    timeoutMs = 120000,
    signal,
    onProgress,
  } = options;

  const startedAt = Date.now();

  while (Date.now() - startedAt < timeoutMs) {
    if (signal?.aborted) {
      throw new DOMException('Task polling was cancelled', 'AbortError');
    }

    const response = await fetch(
      `https://api.notexapp.com/v1/create/tasks/${encodeURIComponent(taskId)}/result`,
      {
        headers: {
          'X-API-Key': apiKey,
        },
        signal,
      },
    );

    if (!response.ok) {
      throw new Error(`Failed to poll task: HTTP ${response.status}`);
    }

    const result = (await response.json()) as TaskResultResponse<T>;

    if (result.status === 'SUCCESS') {
      return result.data;
    }

    if (result.status === 'FAILURE' || result.status === 'FAIL') {
      throw new Error(
        result.message ??
          result.error ??
          result.error_key ??
          'Task failed',
      );
    }

    onProgress?.(result);

    await new Promise<void>((resolve, reject) => {
      const timer = setTimeout(resolve, intervalMs);

      signal?.addEventListener(
        'abort',
        () => {
          clearTimeout(timer);
          reject(new DOMException('Task polling was cancelled', 'AbortError'));
        },
        { once: true },
      );
    });
  }

  throw new Error('Task polling timed out');
}
TypeScript types
export type TaskStatus =
  | 'PENDING'
  | 'PROCESSING'
  | 'SUCCESS'
  | 'FAILURE'
  | 'FAIL';

export interface PollTaskResultPathParams {
  task_id: string;
}

export interface TaskProcessingResponse {
  status: 'PENDING' | 'PROCESSING';
  step?: string;
  progress?: number;
  estimated_time?: number;
}

export interface TaskSuccessResultData {
  note_id?: string;
  title?: string;
  summary?: string;
  type?: string;
  audio_url?: string;
  youtube_url?: string;
  views?: string;
  [key: string]: unknown;
}

export interface TaskSuccessResponse<
  T = TaskSuccessResultData,
> {
  status: 'SUCCESS';
  data: T;
  message?: string;
}

export interface TaskFailureResponse {
  status: 'FAILURE' | 'FAIL';
  error?: string;
  error_key?: string;
  message?: string;
}

export type TaskResultResponse<
  T = TaskSuccessResultData,
> =
  | TaskProcessingResponse
  | TaskSuccessResponse<T>
  | TaskFailureResponse;

Integration flow

  1. Call a content-creation endpoint.
  2. Save the returned task_id.
  3. Poll the Tasks API every 3–5 seconds.
  4. Display step or progress when available.
  5. Stop on SUCCESS, FAILURE, or FAIL.
  6. Use data when the task succeeds.

Important notes

  • Result fields differ by task type.
  • Progress information may be omitted.
  • Support both FAILURE and FAIL.
  • Retry temporary network failures without assuming the task failed.
  • Keep the API key on a controlled backend or server.