curl --request GET \
--url https://api.flow.engineer/v1/app \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.flow.engineer/v1/app', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.flow.engineer/v1/app"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.flow.engineer/v1/app"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"account": {
"id": "acct_01JB8YZ3N2Q4R6T8V0X2Z4B6D8",
"name": "<string>",
"plan": "free",
"created_at": "2023-11-07T05:31:56Z"
},
"app": {
"id": "app_01JB8Z0A1C3E5G7J9K1M3P5R7T",
"account": "acct_01JB8YZ3N2Q4R6T8V0X2Z4B6D8",
"name": "<string>",
"api_version": "2023-12-25",
"settings": {
"transcription": true,
"auto_read": true
},
"created_at": "2023-11-07T05:31:56Z",
"sandbox_join_code": "brave-otter-40718263"
},
"api_key": {
"id": "key_01JB8Z1B2D4F6H8K0M2P4R6T8W",
"mode": "test",
"last4": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"expires_at": "2023-11-07T05:31:56Z"
},
"livemode": true,
"allowance": {
"tier": "anonymous",
"scope": "app",
"channels": [
"telegram"
],
"contacts": {
"limit": 1,
"used": 1
},
"messages_per_contact": 1,
"messages": {
"limit": 1,
"used": 1,
"remaining": 1
},
"upgrade": "<string>",
"expires_at": "2023-11-07T05:31:56Z"
}
}{
"error": {
"type": "authentication",
"message": "No valid API key was given.",
"hint": "Send the header Authorization: Bearer fk_test_... (or fk_live_...); no key yet? Get a test key with curl -X POST https://api.flow.engineer/v1/sandbox/keys",
"doc_url": "https://api.flow.engineer/docs/errors/authentication"
}
}{
"error": {
"type": "new_contact_limit",
"message": "This sender has started its 15 new conversations for today.",
"hint": "Retry after 3600 seconds; replies into existing conversations still go.",
"doc_url": "https://api.flow.engineer/docs/errors/new_contact_limit",
"retry_after": 3600,
"sender": "snd_01JB8Z4Q3V6W0R2N7C5H1M9K4T"
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"hint": "Send a template instead: POST /v1/messages with content.type=template.",
"doc_url": "https://api.flow.engineer/docs/errors/outside_window",
"param": "<string>",
"retry_after": 1,
"conversation": "conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1",
"sender": "snd_01JB8Z4Q3V6W0R2N7C5H1M9K4T",
"channel_code": "<string>",
"request_id": "<string>"
}
}Get the calling app
Returns the app, account and API key that made the request, and the mode it runs in. Useful to check a key and to read the app’s pinned API version.
curl --request GET \
--url https://api.flow.engineer/v1/app \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.flow.engineer/v1/app', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.flow.engineer/v1/app"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.flow.engineer/v1/app"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"account": {
"id": "acct_01JB8YZ3N2Q4R6T8V0X2Z4B6D8",
"name": "<string>",
"plan": "free",
"created_at": "2023-11-07T05:31:56Z"
},
"app": {
"id": "app_01JB8Z0A1C3E5G7J9K1M3P5R7T",
"account": "acct_01JB8YZ3N2Q4R6T8V0X2Z4B6D8",
"name": "<string>",
"api_version": "2023-12-25",
"settings": {
"transcription": true,
"auto_read": true
},
"created_at": "2023-11-07T05:31:56Z",
"sandbox_join_code": "brave-otter-40718263"
},
"api_key": {
"id": "key_01JB8Z1B2D4F6H8K0M2P4R6T8W",
"mode": "test",
"last4": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"expires_at": "2023-11-07T05:31:56Z"
},
"livemode": true,
"allowance": {
"tier": "anonymous",
"scope": "app",
"channels": [
"telegram"
],
"contacts": {
"limit": 1,
"used": 1
},
"messages_per_contact": 1,
"messages": {
"limit": 1,
"used": 1,
"remaining": 1
},
"upgrade": "<string>",
"expires_at": "2023-11-07T05:31:56Z"
}
}{
"error": {
"type": "authentication",
"message": "No valid API key was given.",
"hint": "Send the header Authorization: Bearer fk_test_... (or fk_live_...); no key yet? Get a test key with curl -X POST https://api.flow.engineer/v1/sandbox/keys",
"doc_url": "https://api.flow.engineer/docs/errors/authentication"
}
}{
"error": {
"type": "new_contact_limit",
"message": "This sender has started its 15 new conversations for today.",
"hint": "Retry after 3600 seconds; replies into existing conversations still go.",
"doc_url": "https://api.flow.engineer/docs/errors/new_contact_limit",
"retry_after": 3600,
"sender": "snd_01JB8Z4Q3V6W0R2N7C5H1M9K4T"
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"hint": "Send a template instead: POST /v1/messages with content.type=template.",
"doc_url": "https://api.flow.engineer/docs/errors/outside_window",
"param": "<string>",
"retry_after": 1,
"conversation": "conv_01JB8ZC3K5M7P9R1T3V5X7Z9B1",
"sender": "snd_01JB8Z4Q3V6W0R2N7C5H1M9K4T",
"channel_code": "<string>",
"request_id": "<string>"
}
}Authorizations
An API key of one app, sent as Authorization: Bearer <key>. Keys start with
fk_test_ (test mode: sandbox senders and test data only) or fk_live_
(live mode). Keep live keys on your server; never ship them in an app or page.
Headers
The API version to use, as a date. Without it, the version pinned to your app when it was created is used.
"2026-11-01"
Response
The calling app.
Who is calling, as worked out from the API key.
A customer company. Holds the plan, billing and members. Every app belongs to one account.
Show child attributes
Show child attributes
One agent integration. Owns API keys (per mode), webhook endpoints and settings.
Show child attributes
Show child attributes
An API key's record. The key itself is shown once, at creation, and stored only as a hash.
Show child attributes
Show child attributes
true for a live key, false for a test key.
What the app may still send on the shared sandbox senders for free. Present
only on apps that have one: apps made with POST /v1/sandbox/keys
(anonymous, one allowance per app), and apps of people who signed in
(signed_in, one allowance per person: every app the person owns or claimed
draws on the same contacts and messages, so the counts here are the
person's, over all those apps). Only messages your agent sends count, on the
channels in channels; inbound messages are free. A contact counts once it
joins an app on a sandbox sender, and keeps counting after it leaves. Sends
past the allowance answer 403 permission with channel_code
sandbox_allowance_used; a join past contacts.limit is refused in the
chat.
Show child attributes
Show child attributes