# Create a file upload

### Create a file upload

`POST /api/v1/files`

Operation ID: `createFileUpload`

Stores a private object in Needle. Pass filename and contentType to mint a short-lived signed PUT URL, then PUT the bytes to uploadUrl. Or pass sourceUrl to copy a public https file into Needle. Then pass the returned url when sending a LinkedIn message or InMail, or on a campaign send step. downloadUrl is a preview link; do not pass it to LinkedIn.

**Request body** (required)

- `filename` (string, optional)
- `contentType` (string, optional)
- `sourceUrl` (string · uri, optional): Public https URL. Needle copies the file into a private object and returns the url to attach.

**201**: Object identity, a preview URL, and a short-lived upload URL when you still need to PUT bytes.

- `url` (string, required): Private object identity. Store this on a send or a campaign step. Not a download link.
- `uploadUrl` (string | null, required): Short-lived signed PUT URL when you upload bytes yourself. Null when Needle already copied sourceUrl. Discard after use.
- `filename` (string, required)
- `downloadUrl` (string, required): Preview URL on needle.app that redirects to a short-lived signed GET. Do not send this to LinkedIn.
- `expiresAt` (string · date-time, required): When the preview URL stops redirecting. Each visit mints a fresh signature until then.
- `requestId` (string · uuid, required): Id of this request, for support and troubleshooting

**Errors**

- `400`: Bad request
- `401`: Unauthorized: missing or invalid API key
- `403`: Forbidden
- `404`: Not found
- `422`: Invalid request payload
