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.
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
- Host the file somewhere publicly readable over HTTPS, for example object storage.
- 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.
- 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.
Related
- Error reference — the full table of error codes
- Using Repull from AI agents — patterns for handling errors in agent loops
- Sending attachments
- attachment_unreachable
Hit an error that isn't covered? Email hello@repull.dev with the request id from the response headers.