# Add files for dynamic attachments

- Operation ID: `addClientFiles`
- HTTP method: `POST`
- Path: `/uploader-service/clients/files/by/{identifierType}`
- [Human-readable API reference](https://hub.synerise.com/api-reference/asset-management#tag/Uploader/operation/addClientFiles)

## Self-contained OpenAPI method

The fenced document below contains this method's documentation and all of its local references. It is self-contained; no category or master specification fetch is required.

```yaml
openapi: 3.0.0
info:
  title: Synerise Public API
  version: 1.9.5
paths:
  /uploader-service/clients/files/by/{identifierType}:
    post:
      tags:
        - Uploader
      summary: Add files for dynamic attachments
      description: |
        Add base64 encoded files to the storage for use in [dynamic attachments](https://help.synerise.com/docs/automation/actions/send-email/#dynamic-attachments). You can send up to 5 files in one request. An `attachment.upload` event is generated when you use the endpoint.

        ---

        **API consumers:** <a href="/api-reference/authorization?tag=Authorization&amp;operationId=userLogin" target="_blank" rel="noopener">Synerise User</a>, <a href="/api-reference/authorization?tag=Authorization&amp;operationId=profileLogin" target="_blank" rel="noopener">Workspace (Business Profile)</a>

        **API key permission required:** `UPLOADER_SERVICE_STORAGE_CREATE`

        **User role permission required:** `assets_explorer: create`
      operationId: addClientFiles
      parameters:
        - in: path
          name: identifierType
          description: Type of the profile identifier. The value is sent in `identifierValue` in the request body.
          required: true
          schema:
            type: string
            enum:
              - id
              - uuid
              - email
              - custom_identify
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - files
                - ttlInMinutes
                - identifierValue
                - parameters
              properties:
                files:
                  type: array
                  description: Up to 5 files can be sent at once. The order in the array is reflected in the generated `attachment.upload` event, and the files from the event can then be accessed by their index in the array.
                  items:
                    type: object
                    required:
                      - content
                      - mimetype
                      - filename
                      - extension
                    properties:
                      content:
                        type: string
                        description: The file encoded into base64.
                        example: 77u/dGhpcyBpcyBqdXN0IGFuIGV4YW1wbGUgZmlsZQ==
                      mimetype:
                        type: string
                        description: The media type, in the type/type format, for example `text/csv`
                        example: text/csv
                      filename:
                        type: string
                        description: The name of the file
                        example: myexamplefile
                      extension:
                        type: string
                        description: The extension of the uploaded file
                        example: csv
                ttlInMinutes:
                  description: Defines the amount of time (expressed in minutes) the file or files are available. If this parameter is not sent, the default time to live of the files is 30 days.
                  type: number
                identifierValue:
                  description: Contains the value of a customer identifier a file is dedicated for. The type of the value is defined in the path parameters of the endpoint (`identifierType`). If `id` is used, it must be sent as a string.
                  type: string
                  example: "1234"
                parameters:
                  description: Custom parameters of the files.
                  type: object
                  additionalProperties: true
      responses:
        "200":
          description: File or files uploaded successfully
          content:
            application/json:
              schema:
                type: object
                required:
                  - id
                  - businessProfileId
                  - clientId
                  - ttlInMinutes
                  - params
                  - createdAt
                properties:
                  id:
                    type: string
                    format: uuid
                    description: Unique ID of the file or batch of files
                  businessProfileId:
                    type: number
                    format: int32
                    description: ID of the workspace where the file or files are stored
                  clientId:
                    type: number
                    format: int64
                    example: 1234
                    description: ID of the profile to which the file or files are assigned
                  ttlInMinutes:
                    description: Defines the amount of time (expressed in minutes) the file or files are available. If this parameter is not sent, the default time to live of the files is 30 days.
                    type: number
                  params:
                    description: Custom parameters of the files.
                    type: object
                    additionalProperties: true
                  createdAt:
                    type: string
                    format: date-time
                    description: Date and time when the file or files were created
      security:
        - JWT: []
        - BasicAuth: []
      x-snr-doc-urls:
        - /api-reference/asset-management#tag/Uploader/operation/addClientFiles
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |-
            curl --request POST \
              --url https://api.synerise.com/uploader-service/clients/files/by/%7BidentifierType%7D \
              --header 'Authorization: Basic REPLACE_BASIC_AUTH' \
              --header 'content-type: application/json' \
              --data '{"files":[{"content":"77u/dGhpcyBpcyBqdXN0IGFuIGV4YW1wbGUgZmlsZQ==","mimetype":"text/csv","filename":"myexamplefile","extension":"csv"}],"ttlInMinutes":0,"identifierValue":"1234","parameters":{}}'
        - lang: Python
          label: Python
          source: |-
            import http.client

            conn = http.client.HTTPSConnection("api.synerise.com")

            payload = "{\"files\":[{\"content\":\"77u/dGhpcyBpcyBqdXN0IGFuIGV4YW1wbGUgZmlsZQ==\",\"mimetype\":\"text/csv\",\"filename\":\"myexamplefile\",\"extension\":\"csv\"}],\"ttlInMinutes\":0,\"identifierValue\":\"1234\",\"parameters\":{}}"

            headers = {
                'Authorization': "Basic REPLACE_BASIC_AUTH",
                'content-type': "application/json"
                }

            conn.request("POST", "/uploader-service/clients/files/by/%7BidentifierType%7D", payload, headers)

            res = conn.getresponse()
            data = res.read()

            print(data.decode("utf-8"))
        - lang: JavaScript
          label: JavaScript
          source: |-
            const data = JSON.stringify({
              "files": [
                {
                  "content": "77u/dGhpcyBpcyBqdXN0IGFuIGV4YW1wbGUgZmlsZQ==",
                  "mimetype": "text/csv",
                  "filename": "myexamplefile",
                  "extension": "csv"
                }
              ],
              "ttlInMinutes": 0,
              "identifierValue": "1234",
              "parameters": {}
            });

            const xhr = new XMLHttpRequest();
            xhr.withCredentials = true;

            xhr.addEventListener("readystatechange", function () {
              if (this.readyState === this.DONE) {
                console.log(this.responseText);
              }
            });

            xhr.open("POST", "https://api.synerise.com/uploader-service/clients/files/by/%7BidentifierType%7D");
            xhr.setRequestHeader("Authorization", "Basic REPLACE_BASIC_AUTH");
            xhr.setRequestHeader("content-type", "application/json");

            xhr.send(data);
        - lang: Node.js
          label: Node.js
          source: |-
            const http = require("https");

            const options = {
              "method": "POST",
              "hostname": "api.synerise.com",
              "port": null,
              "path": "/uploader-service/clients/files/by/%7BidentifierType%7D",
              "headers": {
                "Authorization": "Basic REPLACE_BASIC_AUTH",
                "content-type": "application/json"
              }
            };

            const req = http.request(options, function (res) {
              const chunks = [];

              res.on("data", function (chunk) {
                chunks.push(chunk);
              });

              res.on("end", function () {
                const body = Buffer.concat(chunks);
                console.log(body.toString());
              });
            });

            req.write(JSON.stringify({
              files: [
                {
                  content: '77u/dGhpcyBpcyBqdXN0IGFuIGV4YW1wbGUgZmlsZQ==',
                  mimetype: 'text/csv',
                  filename: 'myexamplefile',
                  extension: 'csv'
                }
              ],
              ttlInMinutes: 0,
              identifierValue: '1234',
              parameters: {}
            }));
            req.end();
        - lang: PHP
          label: PHP
          source: |-
            <?php

            $request = new HttpRequest();
            $request->setUrl('https://api.synerise.com/uploader-service/clients/files/by/%7BidentifierType%7D');
            $request->setMethod(HTTP_METH_POST);

            $request->setHeaders([
              'Authorization' => 'Basic REPLACE_BASIC_AUTH',
              'content-type' => 'application/json'
            ]);

            $request->setBody('{"files":[{"content":"77u/dGhpcyBpcyBqdXN0IGFuIGV4YW1wbGUgZmlsZQ==","mimetype":"text/csv","filename":"myexamplefile","extension":"csv"}],"ttlInMinutes":0,"identifierValue":"1234","parameters":{}}');

            try {
              $response = $request->send();

              echo $response->getBody();
            } catch (HttpException $ex) {
              echo $ex;
            }
        - lang: Java
          label: Java
          source: |-
            HttpResponse<String> response = Unirest.post("https://api.synerise.com/uploader-service/clients/files/by/%7BidentifierType%7D")
              .header("Authorization", "Basic REPLACE_BASIC_AUTH")
              .header("content-type", "application/json")
              .body("{\"files\":[{\"content\":\"77u/dGhpcyBpcyBqdXN0IGFuIGV4YW1wbGUgZmlsZQ==\",\"mimetype\":\"text/csv\",\"filename\":\"myexamplefile\",\"extension\":\"csv\"}],\"ttlInMinutes\":0,\"identifierValue\":\"1234\",\"parameters\":{}}")
              .asString();
servers:
  - url: https://api.synerise.com
    description: Microsoft Azure EU
  - url: https://api.azu.synerise.com
    description: Microsoft Azure USA
  - url: https://api.geb.synerise.com
    description: Google Cloud Platform
tags:
  - name: Uploader
components:
  securitySchemes:
    JWT:
      type: http
      scheme: bearer
      description: |
        Synerise uses [JSON Web Token (JWT)](https://jwt.io/) as the authorization method.

        The token is generated by the *auth/login* endpoints.

        You need to include it in the `Authorization` header of your requests, with a `Bearer` prefix.


        By default, the token is valid for **one week** (see [workspace settings](https://hub.synerise.com/docs/settings/tool/iam-for-apps/general/#jwt-lifetime)).  
        You can request a refreshed key for the session by using the *auth/refresh* endpoint **before** the current token expires.


        You can verify your JWT signature by using the [public key](https://api.synerise.com/v4/public.pem).


        See Developer Guides on JWT API authentication for:
        - [profiles](https://hub.synerise.com/developers/api/api-authorization/client-login/);
        - [workspaces](https://hub.synerise.com/developers/api/api-authorization/workspace-login/#api-authentication-with-jwt);
        - [users](https://hub.synerise.com/developers/api/api-authorization/user-login/).
    BasicAuth:
      type: http
      scheme: basic
      description: |
        Basic authentication with login (workspace GUID) and password (workspace API key) encoded with Base64 and sent in the `Authorization` header. **Must be enabled in the settings of the API key**.

        <span style="color:red">This is less secure than JWTs.</span> Limit the API key permissions to only those that you need. Consider API key rotation and other security measures.

        You can still use JWTs from the same API key when basic authentication is enabled.

        For details, see ["Workspace authentication"](https://hub.synerise.com/jwt-or-basic/#basic-api-authentication-with-api-keys).
```
