API KeysPresigned URL

Presigned URL

Upload a local file to Notex and receive a file URL that can be used by Notes and other content-processing APIs.

Presigned URL

A presigned URL allows your application to upload a file directly to Notex storage without sending the file through the main API server.

The upload flow has three steps:

Get an upload URL

Upload the file with PUT

Use file_url with another API

After uploading an audio file, document, or image, you can pass the returned file_url to the Notes API.

Base URL:

https://api.notexapp.com

Send the API key through X-API-Key when requesting a presigned URL:

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

Get a presigned URL

GET /v1/presigned-url

Creates a temporary URL that accepts a direct PUT upload.

Query parameters

ParameterTypeRequiredDescription
file_namestringYesFile name, including its extension
is_publicbooleanNoWhether the stored object should be publicly accessible
user_idstringNoTarget user ID for special device or service integrations

When using a normal API key, omit user_id. The uploaded file is associated with the account that created the key.

Example request

curl --get "https://api.notexapp.com/v1/presigned-url" \
  -H "X-API-Key: ntx_live_..." \
  --data-urlencode "file_name=lecture.mp3"

--data-urlencode safely handles spaces and special characters in file names.

Example response

{
  "statusCode": 200,
  "data": {
    "upload_url": "https://storage.example.com/temporary-upload-url",
    "file_url": "https://cdn.notexapp.com/uploads/lecture.mp3"
  }
}

Response fields

FieldTypeDescription
upload_urlstringTemporary URL used to upload the file with PUT
file_urlstringFile reference passed to another Notex API
file_namestringOriginal file name, when returned
full_pathstringInternal storage path, when returned
presigned_urlstringLegacy name or alias for upload_url, when returned

For new integrations, prefer:

upload_url → upload the file
file_url   → use the uploaded file

Upload the file

Send the file binary directly to upload_url with a PUT request.

Do not include the Notex API key in this request.

curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: audio/mpeg" \
  --data-binary @lecture.mp3

Content types

FileContent-Type
.mp3audio/mpeg
.wavaudio/wav
.m4aaudio/mp4
.mp4video/mp4
.pdfapplication/pdf
.docxapplication/vnd.openxmlformats-officedocument.wordprocessingml.document
.txttext/plain
.jpg, .jpegimage/jpeg
.pngimage/png

If the upload fails, check:

  • Whether the presigned URL has expired.
  • Whether the Content-Type matches the uploaded file.
  • Whether the request body contains the unmodified binary file.
  • Whether the upload URL was changed or encoded again.

Do not modify upload_url. Use it exactly as returned.


Use the uploaded file

After the PUT request succeeds, pass file_url to the next API.

Example:

curl -X POST https://api.notexapp.com/v9/create/note \
  -H "X-API-Key: ntx_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "file_url": "https://cdn.notexapp.com/uploads/lecture.mp3",
    "language_hints": ["en"]
  }'

Do not pass upload_url to the Create Note endpoint.

ValuePurpose
upload_urlUsed only for the direct PUT upload
file_urlUsed as input for Notes and other content APIs

Complete upload flow

# Step 1: Get an upload URL
RESPONSE=$(curl -s --get \
  "https://api.notexapp.com/v1/presigned-url" \
  -H "X-API-Key: ntx_live_..." \
  --data-urlencode "file_name=lecture.mp3")

UPLOAD_URL=$(echo "$RESPONSE" | jq -r '.data.upload_url')
FILE_URL=$(echo "$RESPONSE" | jq -r '.data.file_url')

# Step 2: Upload the file
curl --fail -X PUT "$UPLOAD_URL" \
  -H "Content-Type: audio/mpeg" \
  --data-binary @lecture.mp3

# Step 3: Create a note
curl -X POST https://api.notexapp.com/v9/create/note \
  -H "X-API-Key: ntx_live_..." \
  -H "Content-Type: application/json" \
  -d "{
    "file_url": "$FILE_URL",
    "language_hints": ["en"]
  }"

curl --fail causes the command to return an error for unsuccessful HTTP responses.

JavaScript example

interface PresignedUrlResponse {
  statusCode: number;
  message?: string;
  data: {
    upload_url: string;
    file_url: string;
  };
}

async function uploadFileToNotex(
  file: File,
  apiKey: string,
): Promise<string> {
  const params = new URLSearchParams({
    file_name: file.name,
  });

  const presignedResponse = await fetch(
    `https://api.notexapp.com/v1/presigned-url?${params}`,
    {
      headers: {
        'X-API-Key': apiKey,
      },
    },
  );

  if (!presignedResponse.ok) {
    throw new Error('Failed to get a presigned URL');
  }

  const result =
    (await presignedResponse.json()) as PresignedUrlResponse;

  const uploadResponse = await fetch(result.data.upload_url, {
    method: 'PUT',
    headers: {
      'Content-Type': file.type || 'application/octet-stream',
    },
    body: file,
  });

  if (!uploadResponse.ok) {
    throw new Error('Failed to upload the file');
  }

  return result.data.file_url;
}
TypeScript types
export interface GetPresignedUrlQueryParams {
  file_name: string;
  is_public?: boolean;
  user_id?: string;
}

export interface PresignedUrlData {
  upload_url: string;
  file_url: string;
  file_name?: string;
  full_path?: string;
  presigned_url?: string;
}

export interface GetPresignedUrlResponse {
  statusCode: number;
  message?: string;
  data: PresignedUrlData;
}

Important notes

  • Send the API key only when requesting /v1/presigned-url.
  • Do not send the API key to upload_url.
  • Upload with PUT.
  • Send the raw file binary in the request body.
  • Use the correct Content-Type.
  • Use file_url, not upload_url, with content-processing APIs.
  • Presigned URLs expire.
  • Request a new URL when an existing one expires.
  • Keep the API key and upload orchestration on a controlled backend.
Was this page helpful?