> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nonefivem.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Generate Signed URL

> Generate a pre-signed URL for direct file uploads

Generate a pre-signed URL that allows direct file uploads to NoCloud storage. This is useful for client-side uploads where you don't want to proxy files through your server.

## Authorization

<ParamField header="Authorization" type="string" required>
  Bearer token for authentication. Format: `Bearer <your-api-key>`
</ParamField>

## Required Permission

`STORAGE_WRITE`

## Query Parameters

Query parameters are **optional**. Provide them only if you want to pre-allocate storage for the file. If omitted, a non-allocated signed URL is generated instead.

<ParamField query="contentType" type="string">
  MIME type of the file to upload
</ParamField>

<ParamField query="size" type="number">
  Size of the file in bytes
</ParamField>

<ParamField query="metadata" type="record<string, string | number | boolean>">
  Optional metadata to attach to the file
</ParamField>

## Response

### Without query parameters (non-allocated)

<ResponseField name="url" type="string">
  The pre-signed URL for uploading. Upload to this URL using a **POST** request
  with the file as form data. You can optionally include a `metadata` field in
  the form data.
</ResponseField>

<ResponseField name="expiresAt" type="string">
  ISO 8601 timestamp when the URL expires
</ResponseField>

### With query parameters (pre-allocated)

When query parameters are provided, the response includes additional fields for the pre-allocated media:

<ResponseField name="url" type="string">
  The pre-signed URL for uploading. Upload to this URL using a **PUT** request.
</ResponseField>

<ResponseField name="expiresAt" type="string">
  ISO 8601 timestamp when the URL expires
</ResponseField>

<ResponseField name="mediaId" type="string">
  The ID the file will have after upload
</ResponseField>

<ResponseField name="mediaUrl" type="string">
  The public CDN URL where the file will be accessible after upload
</ResponseField>

<RequestExample>
  ```bash cURL (non-allocated) theme={null}
  curl -X GET "https://api.nonefivem.com/cloud/storage/signed-url" \
    -H "Authorization: Bearer your-api-key"
  ```

  ```bash cURL (pre-allocated) theme={null}
  curl -X GET "https://api.nonefivem.com/cloud/storage/signed-url?contentType=image/png&size=1048576" \
    -H "Authorization: Bearer your-api-key"
  ```

  ```javascript JavaScript (non-allocated) theme={null}
  const response = await fetch(
    "https://api.nonefivem.com/cloud/storage/signed-url",
    {
      headers: {
        Authorization: "Bearer your-api-key"
      }
    }
  );
  const { url, expiresAt } = await response.json();

  // Upload using POST with form data
  const formData = new FormData();
  formData.append("file", fileBuffer);
  // Optionally attach metadata
  formData.append("metadata", JSON.stringify({ category: "screenshots" }));

  await fetch(url, {
    method: "POST",
    body: formData
  });
  ```

  ```javascript JavaScript (pre-allocated) theme={null}
  const params = new URLSearchParams({
    contentType: "image/png",
    size: "1048576"
  });

  const response = await fetch(
    `https://api.nonefivem.com/cloud/storage/signed-url?${params}`,
    {
      headers: {
        Authorization: "Bearer your-api-key"
      }
    }
  );
  const { url, mediaId, mediaUrl } = await response.json();

  // Upload directly to the signed URL using PUT
  await fetch(url, {
    method: "PUT",
    body: fileBuffer,
    headers: {
      "Content-Type": "image/png"
    }
  });
  ```
</RequestExample>

<ResponseExample>
  ```json Non-allocated Response theme={null}
  {
    "url": "https://storage.nocloud.dev/upload/signed/abc123...",
    "expiresAt": "2026-02-06T13:00:00Z"
  }
  ```

  ```json Pre-allocated Response theme={null}
  {
    "url": "https://storage.nocloud.dev/upload/signed/abc123...",
    "expiresAt": "2026-02-06T13:00:00Z",
    "mediaId": "550e8400-e29b-41d4-a716-446655440000",
    "mediaUrl": "https://cdn.nonefivem.com/c/{ORGANIZATION_ID}/550e8400-e29b-41d4-a716-446655440000"
  }
  ```
</ResponseExample>

<Info>
  Signed URLs expire after 15 minutes. Generate a new URL if the upload doesn't
  complete in time.
</Info>

<Card title="Uploading Files Guide" icon="cloud-arrow-up" href="/cloud/api-reference/storage/uploading-files">
  Learn how to upload files using signed URLs with complete examples in multiple
  languages.
</Card>
