Get Public URLs for ClickUp Attachments: No Auth Required

April 11, 2026 · 7 min read

You attached a mockup to a ClickUp task, copied the attachment URL, and sent it to a client. They clicked the link and got a login screen. They do not have a ClickUp account. They cannot see the file.

This happens constantly. ClickUp is excellent for internal project management, but it was not built to serve files publicly. Every attachment lives behind workspace authentication. If the person opening the link is not a member of your ClickUp workspace, the file is invisible to them.

The fix is straightforward: download the file from ClickUp and re-upload it to a public CDN that gives you a permanent, open URL. This guide covers four ways to do that, from a quick manual approach with curl to fully automated workflows with Make and n8n. All of them use FilePost as the public hosting layer.

Why ClickUp Attachments Aren't Public

ClickUp treats every attachment as a private workspace asset. This is by design. When you upload a file to a task, ClickUp stores it in your workspace's storage and generates a URL that is scoped to authenticated workspace members only.

There are three specific constraints that make ClickUp attachment URLs unusable outside the workspace:

This is a reasonable security default for internal project files. But it creates a real problem when you need to share deliverables with clients, embed files in external systems, reference attachments in emails, or pass file URLs to third-party integrations that cannot authenticate with ClickUp.

The Fix: Re-Upload to a Public CDN

The solution is a two-step process: pull the file out of ClickUp, then push it to a service that gives you a public URL. That is exactly what FilePost does.

FilePost is a file upload API built for developers. You POST a file, you get back a permanent CDN URL. The URL is public, it loads fast globally via Cloudflare, and it stays live until you explicitly delete it. No authentication required for viewers.

The flow looks like this:

  1. Download from ClickUp. Use the ClickUp API to fetch the attachment. This requires your ClickUp API token (a personal token or OAuth token with access to the workspace).
  2. Upload to FilePost. Send the downloaded file to the FilePost upload endpoint with your API key.
  3. Use the public URL. FilePost returns a permanent CDN URL. Send it to your client, embed it on a page, store it in a database, or post it back into the ClickUp task as a comment.

Let's walk through the implementation, starting with the simplest method.

Manual Method: curl

If you need to grab a single attachment and make it public, curl is the fastest way. Two commands. No scripts, no setup.

Step 1: Download the Attachment from ClickUp

You need the attachment URL from the ClickUp API. First, get the task's attachments. Replace TASK_ID with your ClickUp task ID and YOUR_CLICKUP_TOKEN with your personal API token (found in ClickUp Settings > Apps):

curl -s \
  -H "Authorization: YOUR_CLICKUP_TOKEN" \
  "https://api.clickup.com/api/v2/task/TASK_ID" \
  | python3 -m json.tool

The response includes an attachments array. Each attachment has a url field. That URL is what you need to download the file. Note that this URL still requires authentication to access directly in a browser.

Download the file:

curl -s \
  -H "Authorization: YOUR_CLICKUP_TOKEN" \
  -o "design-mockup.png" \
  "https://attachments.clickup.com/YOUR_ATTACHMENT_URL"

You now have the file saved locally. The -o flag saves it with the filename you specify.

Step 2: Upload to FilePost

Now upload the downloaded file to FilePost to get a public URL:

curl -X POST https://filepost.dev/v1/upload \
  -H "X-API-Key: YOUR_API_KEY" \
  -F "file=@design-mockup.png"

Response:

{
  "url": "https://cdn.filepost.dev/abc123/design-mockup.png",
  "file_id": "abc123",
  "name": "design-mockup.png",
  "size": 45321
}

That url is public. Anyone can open it. No ClickUp account, no login, no workspace membership. Send it to your client, paste it into an email, embed it in a Notion page. It just works.

One-Liner (Piped)

You can chain both steps into a single command:

curl -s -H "Authorization: YOUR_CLICKUP_TOKEN" \
  "https://attachments.clickup.com/YOUR_ATTACHMENT_URL" \
  | curl -X POST https://filepost.dev/v1/upload \
    -H "X-API-Key: YOUR_API_KEY" \
    -F "file=@-;filename=design-mockup.png"

The @- tells curl to read from stdin, and ;filename= sets the filename for the upload. The output is the same FilePost JSON response with your public URL.

Python Script: Batch Export ClickUp Attachments

If you have multiple tasks with attachments that need public URLs, a Python script is more practical than running curl commands one at a time. The script below connects to the ClickUp API, pulls all attachments from a specified task (or list of tasks), uploads each one to FilePost, and optionally posts the public URL back as a comment on the task.

import requests

CLICKUP_TOKEN = "your_clickup_personal_token"
FILEPOST_API_KEY = "your_filepost_api_key"

CLICKUP_HEADERS = {"Authorization": CLICKUP_TOKEN}
FILEPOST_HEADERS = {"X-API-Key": FILEPOST_API_KEY}


def get_task_attachments(task_id):
    """Fetch a task and return its attachments list."""
    resp = requests.get(
        f"https://api.clickup.com/api/v2/task/{task_id}",
        headers=CLICKUP_HEADERS,
    )
    resp.raise_for_status()
    return resp.json().get("attachments", [])


def download_attachment(attachment):
    """Download a single attachment from ClickUp, return bytes and filename."""
    url = attachment["url"]
    filename = attachment.get("title", url.split("/")[-1])
    resp = requests.get(url, headers=CLICKUP_HEADERS)
    resp.raise_for_status()
    return resp.content, filename


def upload_to_filepost(file_bytes, filename):
    """Upload file bytes to FilePost, return the public CDN URL."""
    resp = requests.post(
        "https://filepost.dev/v1/upload",
        headers=FILEPOST_HEADERS,
        files={"file": (filename, file_bytes)},
    )
    resp.raise_for_status()
    return resp.json()


def post_comment(task_id, comment_text):
    """Post a comment on a ClickUp task with the public URL."""
    requests.post(
        f"https://api.clickup.com/api/v2/task/{task_id}/comment",
        headers={**CLICKUP_HEADERS, "Content-Type": "application/json"},
        json={"comment_text": comment_text},
    )


def process_task(task_id, post_back=True):
    """Download all attachments from a task, upload to FilePost, optionally comment."""
    attachments = get_task_attachments(task_id)
    if not attachments:
        print(f"Task {task_id}: no attachments found.")
        return []

    results = []
    for att in attachments:
        file_bytes, filename = download_attachment(att)
        result = upload_to_filepost(file_bytes, filename)
        public_url = result["url"]
        results.append({"filename": filename, "url": public_url})
        print(f"  {filename} -> {public_url}")

        if post_back:
            post_comment(task_id, f"Public URL for {filename}: {public_url}")

    return results


# --- Usage ---
# Process a single task
task_ids = ["abc123", "def456", "ghi789"]

for tid in task_ids:
    print(f"\nProcessing task {tid}...")
    process_task(tid, post_back=True)

Here is what each function does:

To process an entire ClickUp list, you can first call the /list/{list_id}/task endpoint to get all task IDs, then loop process_task() over each one. The free FilePost plan includes 30 uploads per month. If you are doing bulk exports, the Starter plan ($9/mo) gives you 500 uploads.

Automate with Make

If you want public URLs generated automatically every time someone attaches a file to a ClickUp task, Make (formerly Integromat) is a good option. No code required after the initial setup.

Scenario Overview

The Make scenario has four modules:

  1. ClickUp: Watch Events. Triggers when a new attachment is added to any task in a specified Space or List.
  2. HTTP: Get a File. Downloads the attachment from ClickUp using the attachment URL and your ClickUp API token.
  3. HTTP: Make a Request (FilePost Upload). Sends the downloaded file to the FilePost upload endpoint.
  4. ClickUp: Update Task. Writes the public FilePost URL back to a custom field on the task (or posts it as a comment).

Step 1: Set Up the ClickUp Trigger

Add a ClickUp > Watch Events module as the trigger. Connect your ClickUp account and configure it to watch for taskAttachmentUpdated events in the Space or List where you want automatic public URLs. When a file is attached to a task, this module fires and provides the task ID and attachment metadata.

Step 2: Download the Attachment

Add an HTTP > Get a File module. Set the URL to the attachment URL from the trigger output. Under Headers, add Authorization with your ClickUp personal API token. This downloads the file into Make's internal buffer.

Step 3: Upload to FilePost

Add an HTTP > Make a Request module with this configuration:

The response will contain the public CDN URL in the url field.

Step 4: Update the ClickUp Task

Add a ClickUp > Update Task module (or Create Task Comment). If you created a custom field called "Public File URL" on your tasks, map the FilePost URL from the previous step into that field. Alternatively, use the Create Task Comment module to post a comment with the link.

Once activated, this scenario runs every time an attachment is added. Your team attaches a file in ClickUp, and within seconds the public URL appears on the task. No manual steps.

Get Public URLs for Your Files

FilePost gives you permanent CDN URLs with a single API call. Free plan includes 30 uploads/month. No credit card required.

Get Your Free API Key

Automate with n8n

If you prefer self-hosted automation or already run n8n, the same workflow is easy to build there. n8n gives you more control over error handling and data transformation.

Workflow Overview

The n8n workflow has four nodes:

  1. Webhook Trigger. Receives ClickUp webhook events when a new attachment is added.
  2. HTTP Request (Download). Downloads the file from ClickUp.
  3. HTTP Request (FilePost Upload). Uploads the file to FilePost.
  4. HTTP Request (ClickUp Comment). Posts the public URL back to the task as a comment.

Step 1: Set Up the Webhook

Add a Webhook node and copy its URL. In ClickUp, go to Settings > Integrations > Webhooks and create a new webhook pointing to that URL. Select the taskAttachmentUpdated event. Now whenever someone attaches a file to a task, ClickUp will POST the event data to your n8n webhook.

Step 2: Download the Attachment

Add an HTTP Request node:

Step 3: Upload to FilePost

Add a second HTTP Request node:

If you have the n8n-nodes-filepost community node installed, you can use the dedicated FilePost node instead of configuring the HTTP Request manually. Either method produces the same result.

Step 4: Post the URL Back to ClickUp

Add a third HTTP Request node:

Activate the workflow. From now on, every attachment added to a ClickUp task in the monitored workspace triggers the flow: download, upload to CDN, post public URL as a comment. Your team sees the public link without leaving ClickUp, and clients or external partners can access the file without any login.

Tips for Production Use

A few things to keep in mind when deploying any of these methods:

FAQ

Are ClickUp attachment URLs public?

No. ClickUp attachment URLs are private by default. Anyone who clicks a ClickUp attachment link must be logged into the workspace that owns the file. If you send the URL to a client or embed it on a public page, it will fail to load. To make a ClickUp attachment publicly accessible, you need to download it and re-upload it to a public file host like FilePost.

How do I share ClickUp files without requiring login?

Download the attachment from ClickUp (manually or via the ClickUp API), then upload it to a public CDN service like FilePost. FilePost returns a permanent public URL that anyone can open without authentication. You can do this manually with curl, automate it with a Python script, or set up a Make or n8n workflow that runs automatically whenever a new attachment is added.

Can I get a permanent URL for ClickUp attachments?

Yes, but not directly from ClickUp. ClickUp attachment URLs are workspace-scoped and require authentication. To get a permanent, publicly accessible URL, download the file from ClickUp and upload it to FilePost. FilePost stores files on a global CDN and the URL never expires unless you explicitly delete the file.

Does FilePost work with ClickUp?

Yes. You can use the ClickUp API to download attachments and the FilePost API to upload them and get public CDN URLs. This works with curl, Python, or any HTTP client. You can also automate the process with Make or n8n so that every new ClickUp attachment automatically gets a public URL.

Try FilePost Free

Get permanent, public CDN URLs for any file. 30 free uploads per month, no credit card required.

Get Your Free API Key