API documentation
Base URL: https://painel.filaflow.com.br/partners/v1
Updated October 12, 2026. Text, image, video, PDF and WAV audio were tested through the integration. See the attachment validation notes below for the evidence and limitations. Examples use placeholders, not customer credentials or conversation IDs.
Authentication
Create an API key for the desired Instagram connection and enable Allow sending Instagram messages. Existing keys remain read-only. Keep the key on your server, never in browser code.
Authorization: Bearer YOUR_API_KEYAPI keys and webhook signing secrets are different. A webhook signing secret cannot authorize API calls. The API key selects the connection automatically.
Postman quick start
- Create an API key under the intended Instagram connection with Allow sending Instagram messages enabled.
- In Postman, create a POST request to
https://painel.filaflow.com.br/partners/v1/messages. - Open Authorization, choose Bearer Token, and paste your API key in the Token field. Do not include the word Bearer in that field.
- Open Headers and enable both rows below.
- Open Body > raw > JSON, enter the example body and replace the recipient placeholder with the customer's numeric ID from an incoming webhook.
- Click Send. An accepted response contains the request ID, connection ID and Meta message ID.
Content-Type: application/json
Idempotency-Key: postman-reply-000001
{
"recipient_id": "CUSTOMER_ID_FROM_INCOMING_WEBHOOK",
"text": "Hello! This is a test message sent through the integration."
}
Which Instagram account sends the message?
Every API key belongs to exactly one connection. All connections share the same endpoint; the Bearer token selects the sender. Do not add connection_id to the request body: it is not accepted. The response includes connection_id for verification. Before sending, call GET /partners/v1/connections with the same token to check the associated username.
recipient_id is the customer, not your business account. Use data.sender.id from an incoming customer message event for this connection. A read receipt or an outgoing echo is not an incoming customer message.
Send a text message
POST https://painel.filaflow.com.br/partners/v1/messagesRequired scope: messages:write. Required headers:
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Idempotency-Key: reply-order-123Request body:
{
"recipient_id": "INSTAGRAM_SCOPED_SENDER_ID",
"text": "Hello! How can we help?"
}Replace the recipient with data.sender.id from an incoming customer message webhook. Do not use the sender of an outgoing is_echo message, a username or a phone number. Text supports 1 to 1000 characters. For media, use attachment instead of text as shown below.
cURL example
curl -X POST 'https://painel.filaflow.com.br/partners/v1/messages' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: reply-order-123' \
-d '{"recipient_id":"INSTAGRAM_SCOPED_SENDER_ID","text":"Hello!"}'
Accepted response · HTTP 200
{
"id": "MESSAGE_REQUEST_UUID",
"connection_id": "CONNECTION_UUID",
"status": "accepted",
"message_id": "META_MESSAGE_ID"
}Accepted means Meta returned a message ID, not proof of delivery or reading. Meta enforces its messaging windows and recipient eligibility. Provider rejections are returned with sanitized error details.
Idempotency-Key is required
This header is mandatory in our API, not a credential or an Instagram account ID. postman-reply-000001 is only an example; your integration can generate a UUID or persist a unique message reference.
- New logical message: generate a new key.
- Retry the same request: keep the same key and identical recipient and text. The API returns the recorded result without another send.
- Different content or connection with the same key: HTTP 409.
Keys allow 8-128 ASCII letters, numbers, dots, underscores, colons or hyphens and are unique within the workspace. Generate and store the key before making the request so it remains available after a timeout.
Postman supports {{$guid}} as a dynamic header value for a new message. It changes on each request, so do not use it to retry a message without duplication. Keep a fixed value when testing retries.
Missing header · HTTP 400
{
"error": "Provide an Idempotency-Key header with 8 to 128 letters, numbers, dots, colons, underscores or hyphens."
}Add or correct the enabled header in Postman's Headers tab, not in the JSON body. This validation error occurs before sending to Meta.
Send an attachment in Postman
Use the same POST endpoint, Bearer token and JSON headers. Give each attachment its own Idempotency-Key, for example postman-image-000001. Choose Body > raw > JSON:
{
"recipient_id": "CUSTOMER_ID_FROM_INCOMING_WEBHOOK",
"attachment": {
"type": "image",
"url": "https://your-domain.com/media/photo.jpg"
}
}Our API accepts these attachment types. Meta determines whether the actual file is eligible for your Instagram account and API flow:
Image: {"type":"image","url":"https://your-domain.com/photo.jpg"}
Video: {"type":"video","url":"https://your-domain.com/video.mp4"}
Audio: {"type":"audio","url":"https://your-domain.com/audio.wav"}
Document: {"type":"file","url":"https://your-domain.com/document.pdf"}Place one of these objects in attachment. Replace example URLs with direct HTTPS file URLs accessible to Meta without cookies or Authorization headers. A local path, base64 data, a login page or a sharing-page URL is not a file URL. Signed download URLs must remain valid while Meta fetches the file.
Exactly one text or one attachment per request. To send text and a file, send two separate requests with different idempotency keys and check each result. Multipart uploads, multiple attachments and attachment captions are not implemented.
Live validation results
- Image (JPEG): Meta accepted the API request; the outgoing image webhook had the same message ID and
is_echo: true. - Video (MP4) and document (PDF): successful tests reported by the workspace owner.
- Audio (WAV): Meta accepted the API request and the workspace owner confirmed successful reception and playback.
- Audio (MP3): the tested MP3 was rejected with code
100, subcode2534080: attachment format not supported. MP3 compatibility is not validated. - Other audio encodings and document formats: not validated in these tests. A successful PDF does not establish support for every file type.
These results apply to the files and connection tested, not every encoding or Meta account configuration.
Working WAV test in Postman
Use a new header Idempotency-Key: postman-audio-wav-000002 for a new message, with the existing endpoint and authorized API key:
{
"recipient_id": "CUSTOMER_ID_FROM_INCOMING_WEBHOOK",
"attachment": {
"type": "audio",
"url": "https://download.samplelib.com/wav/sample-3s.wav"
}
}This public sample succeeded in the live test. It is hosted by a third party; availability can change. Replace the recipient placeholder with the customer's numeric ID.
For audio, use WAV as the validated starting point. If the source is MP3, convert the actual audio to a compatible format before hosting it. Renaming .mp3 to .wav does not convert the content. FilaFlow does not transcode media automatically. M4A and other encodings have not been tested in this integration.
FilaFlow forwards the URL to Meta; it does not download or store the file. File size, encoding, MIME type and supported formats are checked by Meta. Unsupported files return the provider error without falling back to text.
An accepted response requires a message ID returned by Meta; it is not a delivery or read receipt. Check the conversation and correlate the outgoing webhook's data.message.mid with the API's message_id. A timeout remains unknown. Retry with the same key, type and URL; use a new key when changing the file after a definite rejection.
Query message status
GET https://painel.filaflow.com.br/partners/v1/messages/MESSAGE_REQUEST_UUID
Authorization: Bearer YOUR_API_KEYUse the response id, not Meta's message_id. Requires messages:write; only requests from the key's connection are accessible.
accepted: Meta accepted the message.failed: Meta rejected the request; inspecterror.provider_message,error.provider_codeanderror.provider_subcodewhen present.sending: the request is in progress.unknown: acceptance could not be confirmed. Do not automatically resend with a new key.
Sending or unknown results return HTTP 202 from POST. Failed results return HTTP 422. Status queries return HTTP 200 for an accessible request regardless of its state. Interrupted requests become unknown after 90 seconds when queried. There are no automatic send retries.
Read endpoints
GET /partners/v1/connections Scope: connections:read
GET /partners/v1/events Scope: events:readBoth require Bearer authentication and return an items array scoped to the key's connection. Events returns the latest 100 event metadata records: id, connection_id and created_at, not message content. Full incoming content is delivered through webhooks.
Webhook events and signing keys
The destination must be activated in the Webhooks tab. Events are limited to its linked connection. The observed instagram.messaging events include:
data.message.is_echo: true: a message sent by the connected business account.data.read.mid: a read event referencing a message ID.data.message.textwithout an outgoing echo, with the business as recipient: an incoming customer message. Use its sender ID to reply.
Validate the signature over the exact raw request body:
sha256=HEX(HMAC-SHA256(signing_secret, timestamp + "." + raw_body))Read X-FilaFlow-Timestamp, X-FilaFlow-Signature and X-FilaFlow-Key-Ids. Signatures and key IDs are comma-separated when multiple signing keys are active. Verify with constant-time comparison, apply a timestamp tolerance and deduplicate using X-FilaFlow-Event-Id. Return HTTP 2xx after durably accepting the event.
Errors and limits
- 400: invalid body or missing Idempotency-Key.
- 401: invalid, expired or revoked key, or disconnected account.
- 403: missing permission.
- 404: message request not found within this connection.
- 409: idempotency conflict or unavailable Instagram authorization.
- 415: request must use application/json.
- 422: Meta rejected the send; inspect the error details.
- 429: rate limit exceeded.
The API shares a limit of 300 requests per workspace per 15 minutes. Store secrets securely. Revoking a key blocks subsequent requests, but an in-flight request may already have reached Meta.
