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

# Generate Upload URL

> 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.

Generates a short-lived, presigned S3 URL that you can `PUT` a file to directly. Use it for KYC documents on customers or for transaction-related files such as SWIFT invoices.

<Steps>
  <Step title="Request a URL">
    Call `POST /api/v1/media/url` with the target `fileName` and a `type` (`user` for identity documents, `transaction` for transaction files). The response contains a presigned `url` and a stable `key`.
  </Step>

  <Step title="Upload the file">
    Send an HTTP `PUT` to the `url` with the file bytes as the body. Complete the upload before the URL expires.
  </Step>

  <Step title="Reference the file">
    Attach the returned `key` to any follow-up request (for example, the `invoice` field on a SWIFT withdraw, or a document field in [SME Registration](/api-reference/endpoint/sme-registration/register)). The presigned `url` itself expires shortly after issuance and is not accepted downstream.
  </Step>
</Steps>


## OpenAPI

````yaml POST /api/v1/media/url
openapi: 3.1.0
info:
  title: Afriex Business API
  version: 1.0.8
  description: >-
    Welcome to the Afriex Business API. This API allows you to manage customers,
    process payments, handle payouts, and receive real-time notifications via
    webhooks.


    For detailed guidance on authentication, pagination, error handling, and
    webhooks, please refer to the [dedicated guides](https://docs.afriex.com) in
    the top bar. The guide provides a step-by-step instructions to help you
    integrate seamlessly.
  termsOfService: https://www.afriex.com/terms-and-condition
  contact:
    name: Afriex API Support
    email: eng@afriex.co
    url: https://docs.afriex.com
  license:
    name: Proprietary
    url: https://www.afriex.com/terms-and-condition
servers:
  - url: https://sandbox.api.afriex.com
    description: Staging Base URL
  - url: https://api.afriex.com
    description: Production Base URL
security:
  - ApiKey: []
tags:
  - name: Customers
    description: Create and manage your customers.
  - name: Payment Methods
    description: Register and resolve customer payout and collection methods.
  - name: Transactions
    description: Create and track deposits, withdrawals, and swaps.
  - name: Balance
    description: View and top up your business wallet balances.
  - name: Rates
    description: Fetch real-time exchange rates.
  - name: Checkout Sessions
    description: Create hosted checkout sessions.
  - name: Webhooks
    description: Webhook event payloads and sandbox webhook testing.
  - name: Media
    description: Generate presigned URLs for secure file uploads.
paths:
  /api/v1/media/url:
    parameters:
      - $ref: '#/components/parameters/x-api-version'
    post:
      tags:
        - Media
      summary: Generate a presigned URL for file upload
      description: >-
        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.
      operationId: generatePresignedURL
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MediaURLRequest'
            examples:
              upload-user:
                summary: Generate a user KYC upload URL
                value:
                  fileName: passport.png
                  type: user
              upload-transaction:
                summary: Generate a transaction file upload URL
                value:
                  fileName: report.csv
                  type: transaction
      responses:
        '200':
          description: Presigned URL generated successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MediaURLResponse'
              examples:
                url:
                  summary: Presigned URL
                  value:
                    data:
                      url: >-
                        https://s3.amazonaws.com/bucket/key?X-Amz-Algorithm=AWS4-HMAC-SHA256&...
        '400':
          description: Invalid request body.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - Invalid business API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  parameters:
    x-api-version:
      name: x-api-version
      in: header
      required: false
      description: >-
        API version in ISO 8601 format (e.g. 2025-12-28). Defaults to latest
        stable.
      schema:
        type: string
  schemas:
    MediaURLRequest:
      type: object
      required:
        - fileName
      properties:
        fileName:
          type: string
          description: The name of the file to upload.
          examples:
            - document.pdf
        type:
          type: string
          enum:
            - transaction
            - user
          description: >
            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.
    MediaURLResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            url:
              type: string
              description: The presigned URL for the requested upload operation.
              examples:
                - >-
                  https://s3.amazonaws.com/bucket/key?X-Amz-Algorithm=AWS4-HMAC-SHA256&...
            key:
              type: string
              description: >
                A stable reference to the uploaded object. Attach this to a
                later request (e.g. a SWIFT payout invoice) rather than the
                presigned URL, which expires shortly after it is issued.
              examples:
                - 64f0c2a1e4b0a1b2c3d4e5f6/invoice.pdf
    ErrorResponse:
      type: object
      properties:
        code:
          type: string
          description: Machine-readable error code.
        error:
          type: string
          description: Human-readable error message.
        details:
          $ref: '#/components/schemas/ErrorDetails'
    ErrorDetails:
      type: object
      properties:
        errorMessage:
          type: string
          description: Detailed/technical error message.
        friendlyMessage:
          type: string
          description: User-facing error message safe to display.
        data:
          type: object
          description: >-
            Optional caller-safe context for the error. On a customer-create
            uniqueness conflict (EMAIL_ALREADY_EXISTS /
            PHONE_NUMBER_ALREADY_EXISTS) this carries the existing customer's
            id, so you can adopt it without a follow-up lookup.
          properties:
            customerId:
              type: string
              description: Id of the existing customer (on a create conflict).
  securitySchemes:
    ApiKey:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        Static business API key issued from the dashboard. A business can
        provision **multiple API keys**, each scoped to a configurable set of
        **permissions** (e.g. read transactions, create deposits, etc).
        Permissions are chosen per key at creation time in the dashboard and may
        be revoked by deleting the key. Requests made with a key that does not
        include the permission required by the target endpoint will be rejected
        with a `403 Forbidden` response; an unrecognised, malformed or revoked
        key returns `401 Unauthorized`. Manage your keys and their permissions
        under **Developer → API keys** in the dashboard.

````