# Create pre-signed upload

This API generates a pre-signed URL for media uploads. It responds with information required to build a subsequent form data request to upload the media to an S3 bucket. Please refer to [Examples](#examples) below on how to use it.

## Create a presigned media upload

> Creates a pre-signed URL to upload media that can be used when sending messages in a conversation. The maximum fize size is 100MiB.<br>

```json
{"openapi":"3.0.3","info":{"title":"Conversations","version":"v1"},"tags":[{"name":"conversation","description":"Conversations are a collection of messages between two or more participants."}],"servers":[{"url":"https://api.bird.com","description":"Production API"}],"security":[{"accessKey":[]}],"components":{"securitySchemes":{"accessKey":{"description":"Uses the Authorization header: 'AccessKey ' followed by your access key token","scheme":"AccessKey","type":"http"}},"schemas":{"CreatePresignedUpload":{"type":"object","additionalProperties":false,"required":["contentType"],"properties":{"contentType":{"type":"string","description":"The MIME type of the media being uploaded.","minLength":1}}},"PresignedUpload":{"type":"object","additionalProperties":false,"required":["mediaUrl","uploadUrl","uploadMethod","uploadFormData"],"properties":{"mediaUrl":{"type":"string","description":"The URL to use when sending messages with this media. Must be passed in the `attachments` object.","format":"uri"},"uploadUrl":{"type":"string","description":"The URL to upload the media using form data encoding. The media must be sent with the field name `file` in addition to fields in `uploadFormData`.\n","format":"uri"},"uploadMethod":{"type":"string","description":"The method to use when uploading the media, will always be POST."},"uploadFormData":{"type":"object","description":"Form data fields that must be passed in addition to the field `file` when uploading the media to `uploadUrl`.\n"}}},"error.detailed":{"additionalProperties":false,"description":"An error returned from the API that includes additional details about the error. The `details` property can contain any additional information about the error that may be helpful for debugging or understanding the error.\n","properties":{"code":{"description":"A unique code that identifies the error. This code can be used to programmatically identify the error.","minLength":3,"type":"string"},"details":{"additionalProperties":true,"description":"Any additional information about the error that may be helpful for debugging or understanding the error.","type":"object"},"message":{"description":"A human-readable message that describes the error.","minLength":1,"type":"string"}},"required":["code","message"],"title":"DetailedError","type":"object"},"error.validation":{"additionalProperties":false,"description":"A validation error returned from the API. The `details` map keys are JSON paths\npointing into the request body / parameters; values are arrays of human-readable\nmessages describing each problem with that path.\n","properties":{"code":{"description":"A unique code that identifies the error. This code can be used to programmatically identify the error.","minLength":3,"type":"string"},"details":{"additionalProperties":{"items":{"type":"string"},"type":"array"},"description":"Per-field validation messages keyed by JSON path.","type":"object"},"message":{"description":"A human-readable message that describes the error.","minLength":1,"type":"string"}},"required":["code","message"],"title":"ValidationError","type":"object"}},"responses":{"notFound":{"$ref":"#/components/responses/error.response.not_found"},"error.response.not_found":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/error.detailed"}}},"description":"The requested resource was not found."},"validationFailed":{"$ref":"#/components/responses/error.response.invalid_request"},"error.response.invalid_request":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/error.validation"}}},"description":"The request contains invalid parameters or body fields."}}},"paths":{"/workspaces/{workspaceId}/conversations/{conversationId}/presigned-upload":{"post":{"summary":"Create a presigned media upload","operationId":"createPresignedMediaUpload","description":"Creates a pre-signed URL to upload media that can be used when sending messages in a conversation. The maximum fize size is 100MiB.\n","tags":["conversation"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePresignedUpload"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresignedUpload"}}}},"404":{"$ref":"#/components/responses/notFound"},"422":{"$ref":"#/components/responses/validationFailed"}}}}}}
```

## Examples

In the following example, we'll generate a pre-signed upload URL, then use it to upload media, and finally send a message with it:

1. Generate URL

{% tabs %}
{% tab title="Request" %}

```bash
curl -X POST "https://api.bird.com/workspaces/a1405560-c8d3-4b1a-877d-3f449ad95352/conversations/02ec2ac2-ebec-42d3-a5f4-e6f3a9edf418/presigned-upload" \
-H "Authorization: AccessKey abcd"
```

{% endtab %}

{% tab title="Response (200 - OK)" %}

```json
{
  "mediaUrl": "https://media.api.bird.com/workspaces/a1405560-c8d3-4b1a-877d-3f449ad95352/conversations/02ec2ac2-ebec-42d3-a5f4-e6f3a9edf418/media/e867a2ac-2df5-40be-a5d4-e452d7156048",
  "uploadUrl": "https://channels--message-media--151603429280--euw1.s3.eu-west-1.amazonaws.com",
  "uploadMethod": "POST",
  "uploadFormData": {
    "Content-Type": "image/png",
    "acl": "private",
    "bucket": "channels--message-media--151603429280--euw1",
    "key": "a1405560-c8d3-4b1a-877d-3f449ad95352/e867a2ac-2df5-40be-a5d4-e452d7156048",
    "policy": "c29tZSByYW5kb20gYmFzZTY0IHNvbWUgcmFuZG9tIGJhc2U2NCBzb21lIHJhbmRvbSBiYXNlNjQ=",
    "x-amz-algorithm": "AWS4-HMAC-SHA256",
    "x-amz-credential": "ASIAZIY3TY7LKB5VSROM/20241202/us-west-1/s3/aws4_request",
    "x-amz-date": "20241202T151755Z",
    "x-amz-meta-allowed-paths": "/workspaces/a1405560-c8d3-4b1a-877d-3f449ad95352/conversations/02ec2ac2-ebec-42d3-a5f4-e6f3a9edf418/media/e867a2ac-2df5-40be-a5d4-e452d7156048",
    "x-amz-meta-channel-id": "cb4b1ebc-34e6-5a7a-a375-f6f2f131d88f",
    "x-amz-meta-conversation-id": "02ec2ac2-ebec-42d3-a5f4-e6f3a9edf418",
    "x-amz-security-token": "dmJ0h6xCpr/DysEQmSWORwF7HggMJq6GSSAXUCA0lDY=",
    "x-amz-signature": "22986b67e42558bc2f44b970d8a8c0357832540245a5c80df1229f4166c9d73c"
  }
}
```

{% endtab %}
{% endtabs %}

2. Upload media to pre-signed URL

All of the fields in `uploadFormData` from the previous response need to be passed as form data string fields. Additionally, the field `file` must contain the media file you'd like to upload.

The response status is 204 (No Content).

{% tabs %}
{% tab title="Request" %}

```bash
curl 'https://channels--message-media--151603429280--euw1.s3.eu-west-1.amazonaws.com' \
-F 'Content-Type="image/png"' \
-F 'acl="private"' \
-F 'bucket="channels--message-media--151603429280--euw1"' \
-F 'key="a1405560-c8d3-4b1a-877d-3f449ad95352/e867a2ac-2df5-40be-a5d4-e452d7156048"' \
-F 'policy="c29tZSByYW5kb20gYmFzZTY0IHNvbWUgcmFuZG9tIGJhc2U2NCBzb21lIHJhbmRvbSBiYXNlNjQ="' \
-F 'x-amz-algorithm="AWS4-HMAC-SHA256"' \
-F 'x-amz-credential="ASIAZIY3TY7LKB5VSROM/20241202/us-east-2/s3/aws4_request"' \
-F 'x-amz-date="20241202T151755Z"' \
-F 'x-amz-meta-allowed-paths="/workspaces/a1405560-c8d3-4b1a-877d-3f449ad95352/conversations/02ec2ac2-ebec-42d3-a5f4-e6f3a9edf418/media/e867a2ac-2df5-40be-a5d4-e452d7156048"' \
-F 'x-amz-meta-channel-id="cb4b1ebc-34e6-5a7a-a375-f6f2f131d88f"' \
-F 'x-amz-meta-conversation-id="02ec2ac2-ebec-42d3-a5f4-e6f3a9edf418"' \
-F 'x-amz-security-token="dmJ0h6xCpr/DysEQmSWORwF7HggMJq6GSSAXUCA0lDY="' \
-F 'x-amz-signature="22986b67e42558bc2f44b970d8a8c0357832540245a5c80df1229f4166c9d73c"' \
-F 'file=@"./bird.png"'
```

{% endtab %}
{% endtabs %}

3. Send message with media

{% tabs %}
{% tab title="Request" %}

```bash
curl -X POST "https://api.bird.com/workspaces/a1405560-c8d3-4b1a-877d-3f449ad95352/conversations/02ec2ac2-ebec-42d3-a5f4-e6f3a9edf418/messages" \
-H "Content-Type: application/json" \
-H "Authorization: AccessKey abcd" \
-d '{
  "participantType": "accessKey",
  "participantId": "0c0defe3-c98d-46d9-a9bf-febc1e08aa0c",
  "addMissingParticipants": true,
  "recipients": [
    {
      "type": "to",
      "identifierKey": "emailaddress",
      "identifierValue": "some.customer@example.com"
    }
  ],
  "body": {
    "type": "html",
    "html": {
      "attachments": [
        {
          "inline": true,
          "filename": "my_file",
          "mediaUrl": "https://media.api.bird.com/workspaces/a1405560-c8d3-4b1a-877d-3f449ad95352/conversations/02ec2ac2-ebec-42d3-a5f4-e6f3a9edf418/media/e867a2ac-2df5-40be-a5d4-e452d7156048"
        }
      ],
      "html": "<!doctype html><body><img src=\"cid:my_file\"></img></body></html>"
    }
  }
}'
```

{% endtab %}

{% tab title="Response (201 - Created)" %}

```json
{
  "id": "fec68d3d-bd43-4e73-8ef9-15d7b078b20e",
  "conversationId": "02ec2ac2-ebec-42d3-a5f4-e6f3a9edf418",
  "reference": "",
  "sender": {
    "id": "68b80b8d-8060-42df-bda3-73505a8fdb84",
    "type": "accessKey",
    "status": "active",
    "displayName": "My first email key",
    "avatarUrl": ""
  },
  "draft": false,
  "recipients": [
    {
      "type": "to",
      "id": "8f0b5377-2edc-4116-a8e8-6a475f245a04",
      "identifierKey": "emailaddress",
      "identifierValue": "some.customer@example.com",
      "platformAddress": "some.customer@example.com",
      "contactAnnotation": {
        "name": "John Doe"
      }
    }
  ],
  "status": "accepted",
  "source": "conversations",
  "body": {
    "type": "html",
    "html": {
      "html": "<!doctype html><body><img src=\"cid:my_file\"></img></body></html>",
      "attachments": [
        {
          "mediaUrl": "https://media.api.bird.com/workspaces/a1405560-c8d3-4b1a-877d-3f449ad95352/conversations/02ec2ac2-ebec-42d3-a5f4-e6f3a9edf418/media/e867a2ac-2df5-40be-a5d4-e452d7156048",
          "filename": "my_file",
          "inline": true
        }
      ]
    }
  },
  "interactions": null,
  "createdAt": "2024-12-02T17:17:24.419Z",
  "updatedAt": "2024-12-02T17:17:24.419Z"
}
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.bird.com/api/conversations-api/api-reference/conversations-messaging/create-pre-signed-upload.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
