attachment_url_not_allowed

An attachment URL is not a public https:// address Repull can fetch (private address, credentials in the URL, …). Nothing was sent.

HTTP 422The request was understood but refused as sent. Change it before retrying.

When it fires

Repull downloads every attachment from the URL you give it, and it only fetches public https:// addresses on the open internet. This fires when one of the URLs is not one of those, for example:

  • it points at a private, internal or loopback address, or a redirect leads to one;
  • it carries a username or password in the URL itself;
  • its host name does not resolve;
  • it redirects more than 3 times, or redirects without saying where to.

index and field name the file, and the reason in message is kept deliberately general. Nothing was sent. (A URL that is not https:// at all is refused before any download as 422 invalid_params naming attachments[i].url.)

Response shape

Every Repull error follows the same envelope. The code is stable and safe to switch on.

{
  "error": {
    "code": "attachment_url_not_allowed",
    "message": "Attachment 0: the URL cannot be fetched (private-address). Nothing was sent.",
    "fix": "Attachment URLs must be public `https://` links on the open internet — no credentials in the URL, no private or internal addresses. A signed S3/GCS/Supabase URL valid for a few minutes works.",
    "docs_url": "https://repull.dev/docs/errors/attachment_url_not_allowed",
    "request_id": "req_01J5X7Y8Z9ABCDEF12345678",
    "field": "attachments[0]",
    "channel": "airbnb",
    "index": 0
  }
}

How to fix

  1. Host the file somewhere publicly readable over HTTPS, for example object storage.
  2. If the file is private, generate a short-lived signed URL (a few minutes is plenty) and pass that. Put access in the URL's signature, not in a username and password.
  3. Send the request again with the new URL.

Common gotchas

  • A file on your own laptop, a VPN or an office network cannot be reached. Upload it first.
  • File uploads in the request body are not accepted; attachments always go by URL.

Examples

curl

curl -X POST https://api.repull.dev/v1/conversations/164743/messages \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"attachments": [{"url": "https://your-bucket.s3.amazonaws.com/map.jpg?X-Amz-Signature=..."}]}'

TypeScript

import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3'
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'

// A signed URL valid for five minutes is enough: Repull copies the file right away
const url = await getSignedUrl(new S3Client({}), new GetObjectCommand({ Bucket: 'your-bucket', Key: 'map.jpg' }), {
  expiresIn: 300,
})

await fetch('https://api.repull.dev/v1/conversations/164743/messages', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.REPULL_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ message: 'Here is the parking map.', attachments: [{ url }] }),
})

If you're an AI agent

An attachment URL is not a public https:// address Repull can fetch. Nothing was sent. Re-host the file publicly or use a short-lived signed https URL, then send again.

Hit an error that isn't covered? Email hello@repull.dev with the request id from the response headers.

AI