---
title: "Generate a presigned URL for file upload"
method: POST
path: "/api/v1/media/url"
tags: ["Media"]
---

# Generate a presigned URL for file upload

`POST /api/v1/media/url`

## Request

- Base URL: `https://sandbox.api.afriex.com`
- URL: `https://sandbox.api.afriex.com/api/v1/media/url`
- Auth: API key in header `x-api-key`
- TypeScript: <https://skmtc.dev/afriex/apis/afriex-business-api/docs/api/v1/media/url/post.ts> (a function with typed inputs; its response is checked against the schema)

Generates a presigned S3 URL that the caller can use to upload a file (e.g. a KYC document) directly to Afriex's secure storage. The returned URL is time-limited and scoped to the requested operation. The file name is sanitised before it is used: any directory part is dropped, characters outside `A-Z a-z 0-9 . _ -` become `_`, and the result is cut to 200 characters. The object is stored as `{businessId}/{sanitisedName}`, so always use the returned `key`, not the name you sent, when you reference the file in a later request.

## Request body

- MediaURLRequest
  - `fileName` string, required: The name of the file to upload. It is sanitised (directory parts removed, characters outside `A-Z a-z 0-9 . _ -` replaced with `_`, cut to 200 characters), so the stored name can differ from this value; use the returned `key`.
  - `type` 'transaction' | 'user': The category of the file being uploaded. Use `transaction` for transaction-related files (e.g. a transactions CSV) and `user` for user identity documents. Defaults to `user` when omitted.

## Response `200`

Presigned URL generated successfully.

- MediaURLResponse
  - `data` object
    - `url` string: The presigned URL for the requested upload operation.
    - `key` string: A stable reference to the uploaded object, in the form `{businessId}/{sanitisedFileName}`. Attach this to a later request (e.g. a SWIFT payout invoice) rather than the presigned URL, which expires shortly after it is issued, and rather than the file name you sent, which may have been sanitised.
    - `expiresIn` integer: Number of seconds the presigned URL remains valid for the upload. Complete the PUT upload within this window; afterwards, request a fresh URL.

## Other responses

- `400`: Invalid request body, or a `fileName` that names no file once directory parts and unsafe characters are removed (for example `/`).
- `401`: Unauthorized - Invalid business API key.
- `500`: The upload URL could not be generated. Retry the request.
- `503`: Temporarily unavailable: an upstream service failed or timed out, or the API is momentarily offline. Retry with backoff and honour the Retry-After header when present.

---

[API](https://skmtc.dev/afriex/apis/afriex-business-api.md) - [All operations](https://skmtc.dev/afriex/apis/afriex-business-api/llms.txt) - [OpenAPI document](https://skmtc.dev/afriex/apis/afriex-business-api/revisions/d94198b6c256?raw)
