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

# Add Files

> Add files to an existing post. Posts hold up to 50 files.

Add one or more files to an existing post. The share code, privacy, title and description stay the same. Adding a file to a single-file post turns it into an album.

## Headers

| Header | Required | Description |
| - | - | - |
| `relay-key` | Yes | Your relay key, or the team's access key for a team post |
| `include-metadata` | No | `true` keeps file metadata. Omitted or `false` strips it. |
| `priority` | No | `false` opts the new videos out of priority (adaptive) streaming. |

Send the files as `multipart/form-data`, repeating the `file` field.

## Behavior

* You must own the post. A team post needs that team's access key, and a lapsed team returns `403`.
* Moderated posts cannot be changed and return `403` with type `moderated`.
* A post holds at most **50 files**. A full post, or a request that would go past 50, returns `400`.
* New files take the post's privacy. On a private post their URLs are signed and expire after 24 hours.
* Videos are remuxed to MP4 and metadata is stripped exactly as in [Upload Files](/relay-reference/endpoint/upload). Videos added here do not get a thumbnail.
* Each file is checked against your [weekly quota](/concepts/plans#weekly-usage-limit) on its own. A file that does not fit fails with type `quota_exceeded`.
* Failures work like uploads: stored files come back with `200` and the rest are listed in `failed`. If every file fails, a one-file request returns that file's error and a multi-file request returns `400` with type `upload_failed`. See [Errors](/concepts/errors#partial-upload-failures).
* New files are scanned automatically. If any file, or the post's text, is flagged, the whole post is moderated.
* The response is the full updated post.

## Examples

```bash theme={null}
curl -X POST "https://relay.snipp.gg/posts/AlBm5678/files" \
  -H "relay-key: YOUR_RELAY_KEY" \
  -F "file=@photo3.png"
```

## Responses

```json theme={null}
{
  "post": {
    "code": "AlBm5678",
    "url": "https://snipp.gg/p/AlBm5678",
    "title": "Match highlights",
    "description": null,
    "privacy": "public",
    "created_at": "2026-09-30T18:42:11.512Z",
    "view_count": 128,
    "like_count": 42,
    "comment_count": 3,
    "priority": false,
    "file_count": 3,
    "files": [
      {
        "name": "a1b2c3d4e5f6789012345678abcdef01.png",
        "url": "https://i.snipp.gg/123456789012345678/a1b2c3d4e5f6789012345678abcdef01.png",
        "size": 2487312,
        "mime_type": "image/png",
        "width": 1920,
        "height": 1080,
        "thumbnail_url": null
      },
      {
        "name": "b2c3d4e5f6789012345678abcdef0102.png",
        "url": "https://i.snipp.gg/123456789012345678/b2c3d4e5f6789012345678abcdef0102.png",
        "size": 1843210,
        "mime_type": "image/png",
        "width": 1280,
        "height": 720,
        "thumbnail_url": null
      },
      {
        "name": "f6789012345678abcdef010203040506.png",
        "url": "https://i.snipp.gg/123456789012345678/f6789012345678abcdef010203040506.png",
        "size": 912384,
        "mime_type": "image/png",
        "width": 1080,
        "height": 1920,
        "thumbnail_url": null
      }
    ],
    "team_id": null,
    "author": {
      "id": "123456789012345678",
      "username": "playerone",
      "nickname": "Player One",
      "avatar": "https://i.snipp.gg/avatars/123456789012345678/7e1f0a2b3c4d5e6f708192a3b4c5d6e7.png",
      "verified": false,
      "plan": "plus"
    },
    "liked": false,
    "moderated": false,
    "restricted": false
  }
}
```

One of two files failed:

```json theme={null}
{
  "post": {
    "code": "AlBm5678",
    "url": "https://snipp.gg/p/AlBm5678",
    "title": "Match highlights",
    "description": null,
    "privacy": "public",
    "created_at": "2026-09-30T18:42:11.512Z",
    "view_count": 128,
    "like_count": 42,
    "comment_count": 3,
    "priority": false,
    "file_count": 2,
    "files": [
      {
        "name": "a1b2c3d4e5f6789012345678abcdef01.png",
        "url": "https://i.snipp.gg/123456789012345678/a1b2c3d4e5f6789012345678abcdef01.png",
        "size": 2487312,
        "mime_type": "image/png",
        "width": 1920,
        "height": 1080,
        "thumbnail_url": null
      },
      {
        "name": "b2c3d4e5f6789012345678abcdef0102.png",
        "url": "https://i.snipp.gg/123456789012345678/b2c3d4e5f6789012345678abcdef0102.png",
        "size": 1843210,
        "mime_type": "image/png",
        "width": 1280,
        "height": 720,
        "thumbnail_url": null
      }
    ],
    "team_id": null,
    "author": {
      "id": "123456789012345678",
      "username": "playerone",
      "nickname": "Player One",
      "avatar": "https://i.snipp.gg/avatars/123456789012345678/7e1f0a2b3c4d5e6f708192a3b4c5d6e7.png",
      "verified": false,
      "plan": "plus"
    },
    "liked": false,
    "moderated": false,
    "restricted": false
  },
  "failed": [
    {
      "index": 1,
      "error": {
        "type": "unsupported_type",
        "message": "Unsupported file type."
      }
    }
  ]
}
```

## Errors

| Status | Type | When |
| - | - | - |
| `400` | `invalid_request` | No file, too many files, a bad header value, or a corrupt video |
| `400` | `unsupported_type` | The only file is not a supported type |
| `400` | `quota_exceeded` | The only file would exceed your weekly quota |
| `400` | `upload_failed` | Every file of a multi-file request failed |
| `401` | `unauthorized` | Missing or invalid key |
| `403` | `forbidden` | Not your post, no gallery access, or a lapsed team |
| `403` | `moderated` | The post is moderated |
| `404` | `not_found` | No such post |
| `413` | `file_too_large` | The only file is over your per-file limit |
| `429` | `rate_limited` | More than 10 requests per minute |


## OpenAPI

````yaml relay-reference/openapi.json POST /posts/{code}/files
openapi: 3.0.0
info:
  title: Snipp.gg Relay API
  description: >-
    First-party Snipp API for the full user experience: uploads, posts,
    discover, likes, comments, notifications, blocks and profile management.
  version: 3.0.0
servers:
  - url: https://relay.snipp.gg
    description: Default. Load-balanced across regions. No upload cap.
  - url: https://eu-west-1.relay.snipp.gg
    description: EU West regional endpoint. Pins uploads and storage to EU West.
  - url: https://us-west-1.relay.snipp.gg
    description: US West regional endpoint. Pins uploads and storage to US West.
  - url: https://pulsar.snipp.gg
    description: Alternative host. Capped at 100 MB per upload.
security:
  - relayKeyAuth: []
paths:
  /posts/{code}/files:
    post:
      summary: Add Files
      description: Add files to an existing post. Posts hold up to 50 files.
      operationId: addFiles
      parameters:
        - $ref: '#/components/parameters/PostCode'
        - $ref: '#/components/parameters/IncludeMetadata'
        - $ref: '#/components/parameters/Priority'
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: array
                  items:
                    type: string
                    format: binary
                  description: One or more files. Repeat the `file` field.
              required:
                - file
      responses:
        '200':
          description: Success
          headers:
            request-id:
              $ref: '#/components/headers/RequestId'
          content:
            application/json:
              schema:
                type: object
                properties:
                  post:
                    $ref: '#/components/schemas/Post'
                  failed:
                    type: array
                    items:
                      $ref: '#/components/schemas/FailedFile'
                required:
                  - post
              examples:
                all:
                  summary: All files stored
                  value:
                    post:
                      code: AlBm5678
                      url: https://snipp.gg/p/AlBm5678
                      title: Match highlights
                      description: null
                      privacy: public
                      created_at: '2026-09-30T18:42:11.512Z'
                      view_count: 128
                      like_count: 42
                      comment_count: 3
                      priority: false
                      file_count: 3
                      files:
                        - name: a1b2c3d4e5f6789012345678abcdef01.png
                          url: >-
                            https://i.snipp.gg/123456789012345678/a1b2c3d4e5f6789012345678abcdef01.png
                          size: 2487312
                          mime_type: image/png
                          width: 1920
                          height: 1080
                          thumbnail_url: null
                        - name: b2c3d4e5f6789012345678abcdef0102.png
                          url: >-
                            https://i.snipp.gg/123456789012345678/b2c3d4e5f6789012345678abcdef0102.png
                          size: 1843210
                          mime_type: image/png
                          width: 1280
                          height: 720
                          thumbnail_url: null
                        - name: f6789012345678abcdef010203040506.png
                          url: >-
                            https://i.snipp.gg/123456789012345678/f6789012345678abcdef010203040506.png
                          size: 912384
                          mime_type: image/png
                          width: 1080
                          height: 1920
                          thumbnail_url: null
                      team_id: null
                      author:
                        id: '123456789012345678'
                        username: playerone
                        nickname: Player One
                        avatar: >-
                          https://i.snipp.gg/avatars/123456789012345678/7e1f0a2b3c4d5e6f708192a3b4c5d6e7.png
                        verified: false
                        plan: plus
                      liked: false
                      moderated: false
                      restricted: false
                partial:
                  summary: One file failed
                  value:
                    post:
                      code: AlBm5678
                      url: https://snipp.gg/p/AlBm5678
                      title: Match highlights
                      description: null
                      privacy: public
                      created_at: '2026-09-30T18:42:11.512Z'
                      view_count: 128
                      like_count: 42
                      comment_count: 3
                      priority: false
                      file_count: 2
                      files:
                        - name: a1b2c3d4e5f6789012345678abcdef01.png
                          url: >-
                            https://i.snipp.gg/123456789012345678/a1b2c3d4e5f6789012345678abcdef01.png
                          size: 2487312
                          mime_type: image/png
                          width: 1920
                          height: 1080
                          thumbnail_url: null
                        - name: b2c3d4e5f6789012345678abcdef0102.png
                          url: >-
                            https://i.snipp.gg/123456789012345678/b2c3d4e5f6789012345678abcdef0102.png
                          size: 1843210
                          mime_type: image/png
                          width: 1280
                          height: 720
                          thumbnail_url: null
                      team_id: null
                      author:
                        id: '123456789012345678'
                        username: playerone
                        nickname: Player One
                        avatar: >-
                          https://i.snipp.gg/avatars/123456789012345678/7e1f0a2b3c4d5e6f708192a3b4c5d6e7.png
                        verified: false
                        plan: plus
                      liked: false
                      moderated: false
                      restricted: false
                    failed:
                      - index: 1
                        error:
                          type: unsupported_type
                          message: Unsupported file type.
        '400':
          $ref: '#/components/responses/E400'
        '401':
          $ref: '#/components/responses/E401'
        '403':
          $ref: '#/components/responses/E403'
        '404':
          $ref: '#/components/responses/E404'
        '405':
          $ref: '#/components/responses/E405'
        '413':
          $ref: '#/components/responses/E413'
        '429':
          $ref: '#/components/responses/E429'
        '500':
          $ref: '#/components/responses/E500'
components:
  parameters:
    PostCode:
      name: code
      in: path
      required: true
      description: Post share code.
      schema:
        type: string
      example: AbCd1234
    IncludeMetadata:
      name: include-metadata
      in: header
      required: false
      description: '`true` keeps file metadata. Omitted or `false` strips it.'
      schema:
        type: boolean
        default: false
    Priority:
      name: priority
      in: header
      required: false
      description: '`false` opts videos out of priority (adaptive) streaming.'
      schema:
        type: boolean
        default: true
  headers:
    RequestId:
      description: Unique ID for the request. Include it when contacting support.
      schema:
        type: string
        format: uuid
  schemas:
    Post:
      type: object
      properties:
        code:
          type: string
          description: Share code.
        url:
          type: string
          description: >-
            Share page, `https://snipp.gg/p/{code}`. When the account has picked
            another link domain, `https://{domain}/{code}` instead.
        title:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        privacy:
          type: string
          enum:
            - public
            - unlisted
            - private
        created_at:
          type: string
          format: date-time
        view_count:
          type: integer
        like_count:
          type: integer
          description: '`null` on team posts.'
          nullable: true
        comment_count:
          type: integer
        priority:
          type: boolean
          description: At least one video is on priority (adaptive) streaming.
        file_count:
          type: integer
        files:
          type: array
          items:
            $ref: '#/components/schemas/File'
        team_id:
          type: string
          description: Team ID for team posts, otherwise `null`.
          nullable: true
        author:
          $ref: '#/components/schemas/UserRef'
          nullable: true
        liked:
          type: boolean
          description: You liked the post. `null` on team posts.
          nullable: true
        moderated:
          type: boolean
          description: Owner only. Omitted for everyone else.
        restricted:
          type: boolean
          description: Owner only. Omitted for everyone else.
        access:
          type: array
          items:
            allOf:
              - $ref: '#/components/schemas/UserRef'
              - type: object
                properties:
                  suspended:
                    type: boolean
                    description: >-
                      True while that account is suspended. Show the entry
                      dimmed; nothing about the access changes and it returns to
                      normal on unsuspension.
                required:
                  - suspended
          description: >-
            Owner of a personal post only, on `GET` and `PATCH /posts/{code}`:
            users who can open it while private.
      required:
        - code
        - url
        - title
        - description
        - privacy
        - created_at
        - view_count
        - like_count
        - comment_count
        - priority
        - file_count
        - files
        - team_id
        - author
        - liked
    FailedFile:
      type: object
      properties:
        index:
          type: integer
          description: Zero-based position of the file in the request.
        error:
          $ref: '#/components/schemas/ErrorDetail'
      required:
        - index
        - error
      description: >-
        A file that was not stored. `error` has the same shape as a top-level
        error.
    File:
      type: object
      properties:
        name:
          type: string
          description: 'Stored file name: 32 hex characters plus an extension.'
        url:
          type: string
          description: Direct file URL. Signed for 24 hours on private posts.
        size:
          type: integer
          description: Bytes.
          nullable: true
        mime_type:
          type: string
          nullable: true
        width:
          type: integer
          nullable: true
        height:
          type: integer
          nullable: true
        thumbnail_url:
          type: string
          description: Video thumbnail URL, or `null`.
          nullable: true
      required:
        - name
        - url
        - size
        - mime_type
        - width
        - height
        - thumbnail_url
    UserRef:
      type: object
      properties:
        id:
          type: string
          description: User ID (snowflake).
        username:
          type: string
          nullable: true
        nickname:
          type: string
          nullable: true
        avatar:
          type: string
          description: Avatar URL. Falls back to `https://cdn.snipp.gg/avatar.png`.
        verified:
          type: boolean
        plan:
          $ref: '#/components/schemas/Plan'
      required:
        - id
        - username
        - nickname
        - avatar
        - verified
        - plan
      description: A user embedded inside another resource.
    ErrorDetail:
      type: object
      properties:
        type:
          $ref: '#/components/schemas/ErrorType'
        message:
          type: string
          description: Human-readable sentence. Do not match on it; use `type`.
        username:
          type: string
          description: >-
            `suspended` on `GET /users/{id}` only: the suspended user's
            username.
        quota:
          type: integer
          description: >-
            `quota_exceeded` only: the limit, in bytes for the weekly quota or
            minutes for priority minutes.
        used:
          type: integer
          description: >-
            `quota_exceeded` only: usage in the current window, in the same unit
            as `quota`.
        resets_at:
          type: string
          format: date-time
          description: '`quota_exceeded` only: when the window resets.'
          nullable: true
        failed:
          type: array
          items:
            $ref: '#/components/schemas/FailedFile'
          description: '`upload_failed` only: one entry per file.'
      required:
        - type
        - message
    Error:
      type: object
      properties:
        error:
          $ref: '#/components/schemas/ErrorDetail'
      required:
        - error
      description: Every non-2xx response has this body.
    Plan:
      type: string
      enum:
        - free
        - plus
        - ultra
    ErrorType:
      type: string
      enum:
        - invalid_request
        - unauthorized
        - forbidden
        - suspended
        - blocked
        - moderated
        - plan_required
        - not_found
        - method_not_allowed
        - file_too_large
        - unsupported_type
        - quota_exceeded
        - rate_limited
        - upload_failed
        - internal
        - unavailable
      description: Machine-readable error category. See [Errors](/concepts/errors).
  responses:
    E400:
      description: Invalid request
      headers:
        request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    E401:
      description: Missing or invalid key
      headers:
        request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    E403:
      description: Not allowed
      headers:
        request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    E404:
      description: Not found
      headers:
        request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    E405:
      description: Method not allowed
      headers:
        request-id:
          $ref: '#/components/headers/RequestId'
        Allow:
          description: Methods this path accepts.
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    E413:
      description: File too large
      headers:
        request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    E429:
      description: Rate limited
      headers:
        request-id:
          $ref: '#/components/headers/RequestId'
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    E500:
      description: Internal error
      headers:
        request-id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    relayKeyAuth:
      type: apiKey
      in: header
      name: relay-key
      description: Your relay key from snipp.gg/settings/relay

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.