API reference
Base URL https://api.usecrier.com/v1. Every response is wrapped in data.
Workspace
Your workspace and who is calling.
/v1/meWho is calling
Response 200
data
workspaceIdstringrequireduserobject | nullrequiredNull when called with an API key.
user
userIdstringrequiredemailstringoptional
rolestring | nullrequiredThe dashboard user’s role; null with an API key.
curl "https://api.usecrier.com/v1/me" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/me', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/me",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/workspaceGet the workspace
Response 200
data
idstringrequirednamestringrequiredusagestring | nullrequiredrequireApprovalbooleanrequiredPosts by members wait for an owner or admin to approve them.
createdAtstring (date-time)required
curl "https://api.usecrier.com/v1/workspace" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/workspace', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/workspace",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/workspaceUpdate the workspace
Dashboard onlyBody
namestringoptionalusagestringoptionalrequireApprovalbooleanoptionalPosts by members wait for an owner or admin to approve them.
Response 200
data
idstringrequirednamestringrequiredusagestring | nullrequiredrequireApprovalbooleanrequiredPosts by members wait for an owner or admin to approve them.
createdAtstring (date-time)required
curl -X PATCH "https://api.usecrier.com/v1/workspace" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"usage": "api"
}'const res = await fetch('https://api.usecrier.com/v1/workspace', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"usage": "api"
}),
});
const { data } = await res.json();import os, requests
res = requests.patch(
"https://api.usecrier.com/v1/workspace",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
json={
"usage": "api"
},
)
data = res.json()["data"]Team
Members and invitations. Owners and admins manage the team; members publish and answer.
/v1/teamList members and invitations
Response 200
data
membersobject[]requiredmembers
userIdstringrequiredemailstringoptionalrolestringrequiredjoinedAtstring (date-time)requiredyoubooleanrequired
invitationsobject[]requiredinvitations
idstringrequiredemailstringrequiredrolestringrequiredcreatedAtstring (date-time)requiredexpiresAtstring (date-time)required
curl "https://api.usecrier.com/v1/team" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/team', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/team",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/team/invitationsInvite someone
Dashboard onlyReturns a link to send to them. They join by signing in with the invited email.
Body
emailstring (email)requiredWho to invite; they must sign in with this email to accept.
rolestringoptionaladminmanages the team, API keys and webhooks;memberpublishes and answers.
Response 201
data
invitationobjectrequiredinvitation
idstringrequiredemailstringrequiredrolestringrequiredcreatedAtstring (date-time)requiredexpiresAtstring (date-time)required
urlstring (uri)requiredThe link to send. Shown only now; valid for 7 days.
curl -X POST "https://api.usecrier.com/v1/team/invitations" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/team/invitations', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/team/invitations",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/team/invitations/{id}Cancel an invitation
Dashboard onlyParameters
idstringrequired
Response 204
No content
curl -X DELETE "https://api.usecrier.com/v1/team/invitations/key_2b4n6m" \
-H "Authorization: Bearer $CRIER_API_KEY"await fetch('https://api.usecrier.com/v1/team/invitations/key_2b4n6m', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});import os, requests
requests.delete(
"https://api.usecrier.com/v1/team/invitations/key_2b4n6m",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)/v1/team/members/{userId}Change a role
Dashboard onlyParameters
userIdstringrequired
Body
rolestringrequired
Response 200
data
userIdstringrequiredemailstringoptionalrolestringrequiredjoinedAtstring (date-time)requiredyoubooleanrequired
curl -X PATCH "https://api.usecrier.com/v1/team/members/{userId}" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/team/members/{userId}', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.patch(
"https://api.usecrier.com/v1/team/members/{userId}",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/team/members/{userId}Remove someone, or leave
Dashboard onlyParameters
userIdstringrequired
Response 204
No content
curl -X DELETE "https://api.usecrier.com/v1/team/members/{userId}" \
-H "Authorization: Bearer $CRIER_API_KEY"await fetch('https://api.usecrier.com/v1/team/members/{userId}', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});import os, requests
requests.delete(
"https://api.usecrier.com/v1/team/members/{userId}",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)/v1/invitations/acceptAccept an invitation
Dashboard onlyBody
tokenstringrequiredThe token in the invitation link.
Response 200
data
workspaceIdstringrequiredrolestringrequired
curl -X POST "https://api.usecrier.com/v1/invitations/accept" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/invitations/accept', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/invitations/accept",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]Profiles
A profile is one brand or end customer. Social accounts are connected to a profile.
/v1/profilesList profiles
Response 200
data []
idstringrequirednamestringrequiredtimezonestringoptionalexternalIdstringoptionalcreatedAtstring (date-time)requiredupdatedAtstring (date-time)required
curl "https://api.usecrier.com/v1/profiles" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/profiles', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/profiles",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/profilesCreate a profile
Body
namestringrequiredBrand or end-customer name.
timezonestringoptionalIANA timezone, e.g. Europe/Madrid. Used by the queue.
externalIdstringoptionalYour own id for this customer, returned as is.
Response 201
data
idstringrequirednamestringrequiredtimezonestringoptionalexternalIdstringoptionalcreatedAtstring (date-time)requiredupdatedAtstring (date-time)required
curl -X POST "https://api.usecrier.com/v1/profiles" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme",
"timezone": "Europe/Madrid",
"externalId": "customer-42"
}'const res = await fetch('https://api.usecrier.com/v1/profiles', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Acme",
"timezone": "Europe/Madrid",
"externalId": "customer-42"
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/profiles",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
json={
"name": "Acme",
"timezone": "Europe/Madrid",
"externalId": "customer-42"
},
)
data = res.json()["data"]/v1/profiles/{id}Get a profile
Parameters
idstringrequired
Response 200
data
idstringrequirednamestringrequiredtimezonestringoptionalexternalIdstringoptionalcreatedAtstring (date-time)requiredupdatedAtstring (date-time)required
curl "https://api.usecrier.com/v1/profiles/prf_8f2k4d" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/profiles/prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/profiles/prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/profiles/{id}Update a profile
Parameters
idstringrequired
Body
namestringoptionalBrand or end-customer name.
timezonestringoptionalIANA timezone, e.g. Europe/Madrid. Used by the queue.
externalIdstringoptionalYour own id for this customer, returned as is.
Response 200
data
idstringrequirednamestringrequiredtimezonestringoptionalexternalIdstringoptionalcreatedAtstring (date-time)requiredupdatedAtstring (date-time)required
curl -X PATCH "https://api.usecrier.com/v1/profiles/prf_8f2k4d" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Spain"
}'const res = await fetch('https://api.usecrier.com/v1/profiles/prf_8f2k4d', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Acme Spain"
}),
});
const { data } = await res.json();import os, requests
res = requests.patch(
"https://api.usecrier.com/v1/profiles/prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
json={
"name": "Acme Spain"
},
)
data = res.json()["data"]/v1/profiles/{id}Delete a profile
Also disconnects its accounts.
Parameters
idstringrequired
Response 204
No content
curl -X DELETE "https://api.usecrier.com/v1/profiles/prf_8f2k4d" \
-H "Authorization: Bearer $CRIER_API_KEY"await fetch('https://api.usecrier.com/v1/profiles/prf_8f2k4d', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});import os, requests
requests.delete(
"https://api.usecrier.com/v1/profiles/prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)Queue
Recurring weekly slots per profile. Posts sent with queue: true take the next free one.
/v1/profiles/{id}/queueGet a profile's queue
Parameters
idstringrequired
Response 200
data
timezonestringrequiredslotsobject[]requiredslots
dayOfWeekintegerrequired0 = Sunday … 6 = Saturday
timestringrequiredHH:mm
nextSlotsstring (date-time)[]requiredThe next free slots, soonest first.
curl "https://api.usecrier.com/v1/profiles/prf_8f2k4d/queue" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/profiles/prf_8f2k4d/queue', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/profiles/prf_8f2k4d/queue",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/profiles/{id}/queueSet the queue slots
Replaces every slot. Days go from 0 (Sunday) to 6 (Saturday); times are HH:mm in the queue timezone.
Parameters
idstringrequired
Body
timezonestringoptionalslotsobject[]requiredslots
dayOfWeekintegerrequiredtimestringrequired
Response 200
data
timezonestringrequiredslotsobject[]requiredslots
dayOfWeekintegerrequired0 = Sunday … 6 = Saturday
timestringrequiredHH:mm
nextSlotsstring (date-time)[]requiredThe next free slots, soonest first.
curl -X PUT "https://api.usecrier.com/v1/profiles/prf_8f2k4d/queue" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"timezone": "Europe/Madrid",
"slots": [
{
"dayOfWeek": 1,
"time": "09:00"
},
{
"dayOfWeek": 4,
"time": "18:00"
}
]
}'const res = await fetch('https://api.usecrier.com/v1/profiles/prf_8f2k4d/queue', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"timezone": "Europe/Madrid",
"slots": [
{
"dayOfWeek": 1,
"time": "09:00"
},
{
"dayOfWeek": 4,
"time": "18:00"
}
]
}),
});
const { data } = await res.json();import os, requests
res = requests.put(
"https://api.usecrier.com/v1/profiles/prf_8f2k4d/queue",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
json={
"timezone": "Europe/Madrid",
"slots": [
{
"dayOfWeek": 1,
"time": "09:00"
},
{
"dayOfWeek": 4,
"time": "18:00"
}
]
},
)
data = res.json()["data"]/v1/profiles/{id}/queueDelete the queue
Parameters
idstringrequired
Response 204
No content
curl -X DELETE "https://api.usecrier.com/v1/profiles/prf_8f2k4d/queue" \
-H "Authorization: Bearer $CRIER_API_KEY"await fetch('https://api.usecrier.com/v1/profiles/prf_8f2k4d/queue', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});import os, requests
requests.delete(
"https://api.usecrier.com/v1/profiles/prf_8f2k4d/queue",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)Connect
Connect a social account: send the user to the URL, Crier brings them back to your redirectUrl.
/v1/connect/{platform}Start connecting an account
Returns the URL to send the user to. When they finish, Crier redirects to redirectUrl with connected=<platform>&accountId=…, with error=… if it failed, or with select=<sessionId> when the user must pick a page, organization, board, location or profile (Facebook, LinkedIn, Pinterest, Google Business, Snapchat). In that case list the options and select one.
Parameters
platformstringrequiredprofileIdstringrequiredThe profile the account will belong to.
redirectUrlstring (uri)requiredWhere Crier sends the user back when the connection finishes.
Response 200
data
urlstring (uri)requiredSend the user here to authorize the network.
curl "https://api.usecrier.com/v1/connect/instagram?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconnected" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/connect/instagram?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconnected', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/connect/instagram?profileId=prf_8f2k4d&redirectUrl=https%3A%2F%2Fapp.acme.com%2Fconnected",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/connect/sessions/{id}/optionsList what the user can pick
The id is the select value Crier added to your redirectUrl. Sessions expire after one hour.
Parameters
idstringrequired
Response 200
data
platformstringrequiredoptionsobject[]requiredoptions
idstringrequirednamestringrequireddetailstringoptionalimageUrlstring (uri)optional
curl "https://api.usecrier.com/v1/connect/sessions/cs_5t2y8u/options" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/connect/sessions/cs_5t2y8u/options', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/connect/sessions/cs_5t2y8u/options",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/connect/sessions/{id}/selectPick an option and finish connecting
Parameters
idstringrequired
Body
optionIdstringrequired
Response 201
data
idstringrequiredprofileIdstringrequiredplatformstringrequiredusernamestringoptionaldisplayNamestringoptionalavatarUrlstring (uri)optionalstatusstringrequiredconnectedAtstring (date-time)requiredupdatedAtstring (date-time)required
curl -X POST "https://api.usecrier.com/v1/connect/sessions/cs_5t2y8u/select" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"optionId": "1042…"
}'const res = await fetch('https://api.usecrier.com/v1/connect/sessions/cs_5t2y8u/select', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"optionId": "1042…"
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/connect/sessions/cs_5t2y8u/select",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
json={
"optionId": "1042…"
},
)
data = res.json()["data"]Accounts
Connected social accounts, whether they can post, and their boards, playlists and subreddits.
/v1/accountsList connected accounts
Parameters
profileIdstringoptional
Response 200
data []
idstringrequiredprofileIdstringrequiredplatformstringrequiredusernamestringoptionaldisplayNamestringoptionalavatarUrlstring (uri)optionalstatusstringrequiredconnectedAtstring (date-time)requiredupdatedAtstring (date-time)required
curl "https://api.usecrier.com/v1/accounts?profileId=prf_8f2k4d" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/accounts?profileId=prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/accounts?profileId=prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/accounts/healthCheck whether accounts can post
Asks each network right now. Accounts that need reconnecting are updated to needs_reconnection.
Parameters
profileIdstringrequired
Response 200
data []
accountIdstringrequiredplatformstringrequiredstatusstringrequiredcanPostbooleanrequiredneedsReconnectionbooleanrequiredissuesstring[]required
curl "https://api.usecrier.com/v1/accounts/health?profileId=prf_8f2k4d" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/accounts/health?profileId=prf_8f2k4d', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/accounts/health?profileId=prf_8f2k4d",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/accounts/{id}/{kind}List boards, playlists, subreddits or flairs
kind is pinterest-boards, youtube-playlists, reddit-subreddits or reddit-flairs (with subreddit). Use the ids in the post options.
Parameters
idstringrequiredkindstringrequiredsubredditstringoptionalRequired for reddit-flairs.
Response 200
data []
idstringrequiredSend it as boardId, playlistId, subreddit or flairId.
namestringrequireddetailstringoptionalisDefaultbooleanoptionalThe account's default, used when a post does not pick one.
curl "https://api.usecrier.com/v1/accounts/acc_3k9x2m/{kind}" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/accounts/acc_3k9x2m/{kind}', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/accounts/acc_3k9x2m/{kind}",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/accounts/{id}Disconnect an account
Parameters
idstringrequired
Response 204
No content
curl -X DELETE "https://api.usecrier.com/v1/accounts/acc_3k9x2m" \
-H "Authorization: Bearer $CRIER_API_KEY"await fetch('https://api.usecrier.com/v1/accounts/acc_3k9x2m', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});import os, requests
requests.delete(
"https://api.usecrier.com/v1/accounts/acc_3k9x2m",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)Account groups
Saved selections of accounts, to post to them together.
/v1/account-groupsList groups
Response 200
data []
idstringrequirednamestringrequiredaccountIdsstring[]requiredcreatedAtstring (date-time)requiredupdatedAtstring (date-time)required
curl "https://api.usecrier.com/v1/account-groups" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/account-groups', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/account-groups",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/account-groupsCreate a group
Body
namestringrequiredUnique within the workspace.
accountIdsstring[]requiredAccounts of any profile.
Response 201
data
idstringrequirednamestringrequiredaccountIdsstring[]requiredcreatedAtstring (date-time)requiredupdatedAtstring (date-time)required
curl -X POST "https://api.usecrier.com/v1/account-groups" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/account-groups', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/account-groups",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/account-groups/{id}Update a group
Parameters
idstringrequired
Body
namestringoptionalUnique within the workspace.
accountIdsstring[]optionalAccounts of any profile.
Response 200
data
idstringrequirednamestringrequiredaccountIdsstring[]requiredcreatedAtstring (date-time)requiredupdatedAtstring (date-time)required
curl -X PATCH "https://api.usecrier.com/v1/account-groups/key_2b4n6m" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/account-groups/key_2b4n6m', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.patch(
"https://api.usecrier.com/v1/account-groups/key_2b4n6m",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/account-groups/{id}Delete a group
Parameters
idstringrequired
Response 204
No content
curl -X DELETE "https://api.usecrier.com/v1/account-groups/key_2b4n6m" \
-H "Authorization: Bearer $CRIER_API_KEY"await fetch('https://api.usecrier.com/v1/account-groups/key_2b4n6m', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});import os, requests
requests.delete(
"https://api.usecrier.com/v1/account-groups/key_2b4n6m",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)Posts
Publish now, schedule, queue or save drafts to one or many accounts.
/v1/postsCreate a post
Publishes now unless you send scheduledFor, queue: true or draft: true. Each target is one account and can carry its own text, media and network options (instagram, youtube, tiktok…). TikTok targets always need tiktok options.
Body
contentstringrequiredText posted to every target that has no content of its own.
mediaobject[]optionalImages, videos or documents. Upload them first with POST /v1/media/upload-url.
media
typestringrequiredurlstring (uri)requiredaltTextstringoptional
targetsobject[]requiredtargets
accountIdstringrequiredA connected account (GET /v1/accounts).
contentstringoptionalReplaces the post text on this network.
mediaobject[]optionalmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
youtubeobjectoptionalyoutube
titlestringoptionalVideo title (up to 100 characters).
visibilitystringoptionalpublic,unlistedorprivate.madeForKidsbooleanoptionalCOPPA flag. YouTube may limit videos that do not set it.
categoryIdstringoptionalNumeric YouTube category id.
playlistIdstringoptionalAdd it to this playlist.
tagsstring[]optionalTags (500 characters in total).
firstCommentstringoptionalComment posted right after.
thumbnailUrlstring (uri)optionalCustom thumbnail.
containsSyntheticMediabooleanoptionalContains realistic AI-generated or altered content.
notifySubscribersbooleanoptionalfalseuploads it without notifying subscribers.
tiktokobjectoptionaltiktok
privacystringrequiredWho sees it:
public,friends,followersorprivate.allowCommentsbooleanrequiredAllow comments.
allowDuetbooleanoptionalAllow duets.
allowStitchbooleanoptionalAllow stitches.
commercialContentstringoptionalown_brandwhen it promotes your business,paid_partnershipwhen sponsored. Not withprivateprivacy.autoAddMusicbooleanoptionalPhotos only: TikTok may add recommended music.
consenttruerequiredAlways
true: the user saw the preview and agreed to post.
instagramobjectoptionalinstagram
formatstringoptionalfeed,reelorstory. By default images go to the feed and a video is a Reel.shareToFeedbooleanoptionalReels only:
falsekeeps it out of the profile grid.collaboratorsstring[]optionalUp to 3 business or creator usernames invited as collaborators. Not for Stories.
firstCommentstringoptionalComment posted right after. Not for Stories.
coverUrlstring (uri)optionalReels only: cover image.
facebookobjectoptionalfacebook
formatstringoptionalfeed,reelorstory.reelTitlestringoptionalReels only: a title separate from the text.
firstCommentstringoptionalComment posted right after. Not for Stories.
linkedinobjectoptionallinkedin
firstCommentstringoptionalComment posted right after.
disableLinkPreviewbooleanoptionalHide the link preview.
documentTitlestringoptionalTitle of document (PDF) posts.
xobjectoptionalx
threadstring[]optionalThread replies, in order. The post’s text is the first tweet.
replySettingsstringoptionalWho can reply:
following,mentionedUsers,subscribersorverified.
threadsobjectoptionalthreads
threadstring[]optionalThread replies, in order.
topicTagstringoptionalTopic of the post.
firstCommentstringoptionalComment posted right after.
blueskyobjectoptionalbluesky
threadstring[]optionalThread replies, in order.
pinterestobjectoptionalpinterest
titlestringoptionalPin title.
linkstring (uri)optionalWhere the Pin leads.
boardIdstringoptionalBoard. Defaults to the one picked when connecting.
googleBusinessobjectoptionalgoogleBusiness
callToActionobjectoptionalThe post’s button.
callToAction
typestringrequiredlearn_more,book,order,shop,sign_uporcall.urlstring (uri)optionalWhere the button leads. Required except for
call.
telegramobjectoptionaltelegram
parseModestringoptionalText format:
htmlormarkdown.disableLinkPreviewbooleanoptionalHide the link preview.
silentbooleanoptionalSend without sound.
protectContentbooleanoptionalPrevent forwarding or saving it.
snapchatobjectoptionalsnapchat
formatstringoptionalstory(gone after 24 h),saved_story(stays on the profile) orspotlight.
redditobjectoptionalreddit
subredditstringoptionalSubreddit without
r/.titlestringoptionalPost title.
linkstring (uri)optionalMakes it a link post.
flairIdstringoptionalSubreddit flair.
nsfwbooleanoptionalMark it NSFW.
spoilerbooleanoptionalMark it as a spoiler.
scheduledForstring (date-time)optionalWhen to publish (ISO 8601 with offset). Omit to publish now.
timezonestringoptionalIANA timezone that scheduledFor refers to.
queuebooleanoptionalTake the next free slot of the profile's queue.
draftbooleanoptionalSave without publishing or scheduling.
requiresApprovalbooleanoptionalHold it as
pending_approvaluntil an owner or admin approves it. Members of a workspace that requires approval always get it.
Response 201
data
idstringrequiredcontentstringrequiredmediaobject[]requiredmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
targetsobject[]requiredtargets
accountIdstringrequiredplatformstringrequiredcontentstringoptionalmediaobject[]optionalmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
statusstringrequiredurlstring (uri)optionalThe live post, once published.
errorstringoptional
statusstringrequiredscheduledForstring (date-time)optionalapprovalobjectoptionalPresent once the post went through review.
approval
requestedBystringoptionalUser who asked for it; absent when an API key did.
requestedAtstring (date-time)requiredqueuebooleanoptionalApproving puts it in the profile’s queue.
decisionstringoptionaldecidedBystringoptionaldecidedAtstring (date-time)optionalnotestringoptionalWhy it was rejected.
recyclingobjectoptionalPresent once recycling was turned on.
recycling
activebooleanrequiredeveryintegerrequiredunitstringrequiredstartAtstring (date-time)optionalmaxCopiesintegeroptionaluntilstring (date-time)optionalvariationsstring[]optionaltimezonestringoptionalcopiesintegerrequiredCopies created so far.
nextAtstring (date-time)optionalWhen the next copy goes out; absent once it stopped.
lastCopyIdstringoptionalThe latest copy, a post of its own.
recycledFromstringoptionalOn a recycled copy: the original post.
createdAtstring (date-time)requiredupdatedAtstring (date-time)required
curl -X POST "https://api.usecrier.com/v1/posts" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Our autumn collection is here 🍂",
"media": [
{
"type": "image",
"url": "https://cdn.acme.com/autumn.jpg"
}
],
"targets": [
{
"accountId": "acc_3k9x2m"
},
{
"accountId": "acc_9z8y7x",
"youtube": {
"title": "Autumn collection"
}
}
],
"scheduledFor": "2026-10-30T09:00:00+01:00"
}'const res = await fetch('https://api.usecrier.com/v1/posts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"content": "Our autumn collection is here 🍂",
"media": [
{
"type": "image",
"url": "https://cdn.acme.com/autumn.jpg"
}
],
"targets": [
{
"accountId": "acc_3k9x2m"
},
{
"accountId": "acc_9z8y7x",
"youtube": {
"title": "Autumn collection"
}
}
],
"scheduledFor": "2026-10-30T09:00:00+01:00"
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/posts",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
json={
"content": "Our autumn collection is here 🍂",
"media": [
{
"type": "image",
"url": "https://cdn.acme.com/autumn.jpg"
}
],
"targets": [
{
"accountId": "acc_3k9x2m"
},
{
"accountId": "acc_9z8y7x",
"youtube": {
"title": "Autumn collection"
}
}
],
"scheduledFor": "2026-10-30T09:00:00+01:00"
},
)
data = res.json()["data"]/v1/postsList posts
Newest first.
Parameters
limitintegeroptional
Response 200
data []
idstringrequiredcontentstringrequiredmediaobject[]requiredmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
targetsobject[]requiredtargets
accountIdstringrequiredplatformstringrequiredcontentstringoptionalmediaobject[]optionalmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
statusstringrequiredurlstring (uri)optionalThe live post, once published.
errorstringoptional
statusstringrequiredscheduledForstring (date-time)optionalapprovalobjectoptionalPresent once the post went through review.
approval
requestedBystringoptionalUser who asked for it; absent when an API key did.
requestedAtstring (date-time)requiredqueuebooleanoptionalApproving puts it in the profile’s queue.
decisionstringoptionaldecidedBystringoptionaldecidedAtstring (date-time)optionalnotestringoptionalWhy it was rejected.
recyclingobjectoptionalPresent once recycling was turned on.
recycling
activebooleanrequiredeveryintegerrequiredunitstringrequiredstartAtstring (date-time)optionalmaxCopiesintegeroptionaluntilstring (date-time)optionalvariationsstring[]optionaltimezonestringoptionalcopiesintegerrequiredCopies created so far.
nextAtstring (date-time)optionalWhen the next copy goes out; absent once it stopped.
lastCopyIdstringoptionalThe latest copy, a post of its own.
recycledFromstringoptionalOn a recycled copy: the original post.
createdAtstring (date-time)requiredupdatedAtstring (date-time)required
curl "https://api.usecrier.com/v1/posts?limit=20" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/posts?limit=20', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/posts?limit=20",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/posts/importImport posts from a CSV
One post per row, up to 50 rows. Columns: content, accounts (ids separated by |) or group, schedule_time, timezone, queue, draft, media_urls and per-network columns (see the CSV import guide). Send dryRun: true first to check every row without posting.
Body
csvstringrequiredThe CSV text, header row first.
dryRunbooleanoptionalCheck every row without posting.
Response 200
data
totalintegerrequiredvalidintegerrequiredinvalidintegerrequireddryRunbooleanrequiredunknownColumnsstring[]requiredColumns that were ignored.
rowsobject[]requiredrows
rowintegerrequired1-based, header excluded.
okbooleanrequiredpostIdstringoptionalerrorstringoptional
curl -X POST "https://api.usecrier.com/v1/posts/import" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/posts/import', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/posts/import",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/posts/{id}Change a post that is not live
Drafts, scheduled, failed and cancelled posts. Fields you leave out keep their value; targets replaces the whole list. draft: false publishes a draft now, or at scheduledFor, or in the queue.
Parameters
idstringrequired
Body
contentstringoptionalText posted to every target that has no content of its own.
mediaobject[]optionalImages, videos or documents. Upload them first with POST /v1/media/upload-url.
media
typestringrequiredurlstring (uri)requiredaltTextstringoptional
targetsobject[]optionaltargets
accountIdstringrequiredA connected account (GET /v1/accounts).
contentstringoptionalReplaces the post text on this network.
mediaobject[]optionalmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
youtubeobjectoptionalyoutube
titlestringoptionalVideo title (up to 100 characters).
visibilitystringoptionalpublic,unlistedorprivate.madeForKidsbooleanoptionalCOPPA flag. YouTube may limit videos that do not set it.
categoryIdstringoptionalNumeric YouTube category id.
playlistIdstringoptionalAdd it to this playlist.
tagsstring[]optionalTags (500 characters in total).
firstCommentstringoptionalComment posted right after.
thumbnailUrlstring (uri)optionalCustom thumbnail.
containsSyntheticMediabooleanoptionalContains realistic AI-generated or altered content.
notifySubscribersbooleanoptionalfalseuploads it without notifying subscribers.
tiktokobjectoptionaltiktok
privacystringrequiredWho sees it:
public,friends,followersorprivate.allowCommentsbooleanrequiredAllow comments.
allowDuetbooleanoptionalAllow duets.
allowStitchbooleanoptionalAllow stitches.
commercialContentstringoptionalown_brandwhen it promotes your business,paid_partnershipwhen sponsored. Not withprivateprivacy.autoAddMusicbooleanoptionalPhotos only: TikTok may add recommended music.
consenttruerequiredAlways
true: the user saw the preview and agreed to post.
instagramobjectoptionalinstagram
formatstringoptionalfeed,reelorstory. By default images go to the feed and a video is a Reel.shareToFeedbooleanoptionalReels only:
falsekeeps it out of the profile grid.collaboratorsstring[]optionalUp to 3 business or creator usernames invited as collaborators. Not for Stories.
firstCommentstringoptionalComment posted right after. Not for Stories.
coverUrlstring (uri)optionalReels only: cover image.
facebookobjectoptionalfacebook
formatstringoptionalfeed,reelorstory.reelTitlestringoptionalReels only: a title separate from the text.
firstCommentstringoptionalComment posted right after. Not for Stories.
linkedinobjectoptionallinkedin
firstCommentstringoptionalComment posted right after.
disableLinkPreviewbooleanoptionalHide the link preview.
documentTitlestringoptionalTitle of document (PDF) posts.
xobjectoptionalx
threadstring[]optionalThread replies, in order. The post’s text is the first tweet.
replySettingsstringoptionalWho can reply:
following,mentionedUsers,subscribersorverified.
threadsobjectoptionalthreads
threadstring[]optionalThread replies, in order.
topicTagstringoptionalTopic of the post.
firstCommentstringoptionalComment posted right after.
blueskyobjectoptionalbluesky
threadstring[]optionalThread replies, in order.
pinterestobjectoptionalpinterest
titlestringoptionalPin title.
linkstring (uri)optionalWhere the Pin leads.
boardIdstringoptionalBoard. Defaults to the one picked when connecting.
googleBusinessobjectoptionalgoogleBusiness
callToActionobjectoptionalThe post’s button.
callToAction
typestringrequiredlearn_more,book,order,shop,sign_uporcall.urlstring (uri)optionalWhere the button leads. Required except for
call.
telegramobjectoptionaltelegram
parseModestringoptionalText format:
htmlormarkdown.disableLinkPreviewbooleanoptionalHide the link preview.
silentbooleanoptionalSend without sound.
protectContentbooleanoptionalPrevent forwarding or saving it.
snapchatobjectoptionalsnapchat
formatstringoptionalstory(gone after 24 h),saved_story(stays on the profile) orspotlight.
redditobjectoptionalreddit
subredditstringoptionalSubreddit without
r/.titlestringoptionalPost title.
linkstring (uri)optionalMakes it a link post.
flairIdstringoptionalSubreddit flair.
nsfwbooleanoptionalMark it NSFW.
spoilerbooleanoptionalMark it as a spoiler.
scheduledForstring (date-time)optionalWhen to publish (ISO 8601 with offset). Omit to publish now.
timezonestringoptionalIANA timezone that scheduledFor refers to.
queuebooleanoptionalTake the next free slot of the profile's queue.
draftbooleanoptionalSave without publishing or scheduling.
requiresApprovalbooleanoptionalHold it as
pending_approvaluntil an owner or admin approves it. Members of a workspace that requires approval always get it.
Response 200
data
idstringrequiredcontentstringrequiredmediaobject[]requiredmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
targetsobject[]requiredtargets
accountIdstringrequiredplatformstringrequiredcontentstringoptionalmediaobject[]optionalmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
statusstringrequiredurlstring (uri)optionalThe live post, once published.
errorstringoptional
statusstringrequiredscheduledForstring (date-time)optionalapprovalobjectoptionalPresent once the post went through review.
approval
requestedBystringoptionalUser who asked for it; absent when an API key did.
requestedAtstring (date-time)requiredqueuebooleanoptionalApproving puts it in the profile’s queue.
decisionstringoptionaldecidedBystringoptionaldecidedAtstring (date-time)optionalnotestringoptionalWhy it was rejected.
recyclingobjectoptionalPresent once recycling was turned on.
recycling
activebooleanrequiredeveryintegerrequiredunitstringrequiredstartAtstring (date-time)optionalmaxCopiesintegeroptionaluntilstring (date-time)optionalvariationsstring[]optionaltimezonestringoptionalcopiesintegerrequiredCopies created so far.
nextAtstring (date-time)optionalWhen the next copy goes out; absent once it stopped.
lastCopyIdstringoptionalThe latest copy, a post of its own.
recycledFromstringoptionalOn a recycled copy: the original post.
createdAtstring (date-time)requiredupdatedAtstring (date-time)required
curl -X PATCH "https://api.usecrier.com/v1/posts/pst_7q1w0e" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.patch(
"https://api.usecrier.com/v1/posts/pst_7q1w0e",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/posts/{id}Get a post
Parameters
idstringrequired
Response 200
data
idstringrequiredcontentstringrequiredmediaobject[]requiredmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
targetsobject[]requiredtargets
accountIdstringrequiredplatformstringrequiredcontentstringoptionalmediaobject[]optionalmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
statusstringrequiredurlstring (uri)optionalThe live post, once published.
errorstringoptional
statusstringrequiredscheduledForstring (date-time)optionalapprovalobjectoptionalPresent once the post went through review.
approval
requestedBystringoptionalUser who asked for it; absent when an API key did.
requestedAtstring (date-time)requiredqueuebooleanoptionalApproving puts it in the profile’s queue.
decisionstringoptionaldecidedBystringoptionaldecidedAtstring (date-time)optionalnotestringoptionalWhy it was rejected.
recyclingobjectoptionalPresent once recycling was turned on.
recycling
activebooleanrequiredeveryintegerrequiredunitstringrequiredstartAtstring (date-time)optionalmaxCopiesintegeroptionaluntilstring (date-time)optionalvariationsstring[]optionaltimezonestringoptionalcopiesintegerrequiredCopies created so far.
nextAtstring (date-time)optionalWhen the next copy goes out; absent once it stopped.
lastCopyIdstringoptionalThe latest copy, a post of its own.
recycledFromstringoptionalOn a recycled copy: the original post.
createdAtstring (date-time)requiredupdatedAtstring (date-time)required
curl "https://api.usecrier.com/v1/posts/pst_7q1w0e" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/posts/pst_7q1w0e",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/posts/{id}Delete a post
Removes it from Crier. A post that is still live must be unpublished first.
Parameters
idstringrequired
Response 204
No content
curl -X DELETE "https://api.usecrier.com/v1/posts/pst_7q1w0e" \
-H "Authorization: Bearer $CRIER_API_KEY"await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});import os, requests
requests.delete(
"https://api.usecrier.com/v1/posts/pst_7q1w0e",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)/v1/posts/{id}/editEdit the text of a live post
On X (Premium accounts, within 1 hour), Facebook, LinkedIn, YouTube, Pinterest, Google Business, Telegram, Discord and Reddit. Media cannot change.
Parameters
idstringrequired
Body
contentstringrequiredThe new text of the live post.
accountIdstringoptionalEdit only this account’s copy; every live copy otherwise.
Response 200
data
idstringrequiredcontentstringrequiredmediaobject[]requiredmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
targetsobject[]requiredtargets
accountIdstringrequiredplatformstringrequiredcontentstringoptionalmediaobject[]optionalmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
statusstringrequiredurlstring (uri)optionalThe live post, once published.
errorstringoptional
statusstringrequiredscheduledForstring (date-time)optionalapprovalobjectoptionalPresent once the post went through review.
approval
requestedBystringoptionalUser who asked for it; absent when an API key did.
requestedAtstring (date-time)requiredqueuebooleanoptionalApproving puts it in the profile’s queue.
decisionstringoptionaldecidedBystringoptionaldecidedAtstring (date-time)optionalnotestringoptionalWhy it was rejected.
recyclingobjectoptionalPresent once recycling was turned on.
recycling
activebooleanrequiredeveryintegerrequiredunitstringrequiredstartAtstring (date-time)optionalmaxCopiesintegeroptionaluntilstring (date-time)optionalvariationsstring[]optionaltimezonestringoptionalcopiesintegerrequiredCopies created so far.
nextAtstring (date-time)optionalWhen the next copy goes out; absent once it stopped.
lastCopyIdstringoptionalThe latest copy, a post of its own.
recycledFromstringoptionalOn a recycled copy: the original post.
createdAtstring (date-time)requiredupdatedAtstring (date-time)required
curl -X POST "https://api.usecrier.com/v1/posts/pst_7q1w0e/edit" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e/edit', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/posts/pst_7q1w0e/edit",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/posts/{id}/metricsGet the metrics of a post
Impressions, reach, views, likes, comments, shares, saves and clicks, in total and per account. Each network reports its own subset.
Parameters
idstringrequired
Response 200
data
totalobjectrequiredtotal
impressionsintegerrequiredreachintegerrequiredviewsintegerrequiredlikesintegerrequiredcommentsintegerrequiredsharesintegerrequiredsavesintegerrequiredclicksintegerrequiredengagementRatenumberrequiredPercentage: interactions over impressions (or reach).
targetsobject[]requiredtargets
accountIdstringrequiredplatformstringrequiredmetricsobjectrequiredmetrics
impressionsintegerrequiredreachintegerrequiredviewsintegerrequiredlikesintegerrequiredcommentsintegerrequiredsharesintegerrequiredsavesintegerrequiredclicksintegerrequiredengagementRatenumberrequiredPercentage: interactions over impressions (or reach).
updatedAtstring (date-time)optional
curl "https://api.usecrier.com/v1/posts/pst_7q1w0e/metrics" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e/metrics', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/posts/pst_7q1w0e/metrics",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/posts/{id}/cancelCancel a scheduled post, draft or post waiting for approval
Parameters
idstringrequired
Response 200
data
idstringrequiredcontentstringrequiredmediaobject[]requiredmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
targetsobject[]requiredtargets
accountIdstringrequiredplatformstringrequiredcontentstringoptionalmediaobject[]optionalmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
statusstringrequiredurlstring (uri)optionalThe live post, once published.
errorstringoptional
statusstringrequiredscheduledForstring (date-time)optionalapprovalobjectoptionalPresent once the post went through review.
approval
requestedBystringoptionalUser who asked for it; absent when an API key did.
requestedAtstring (date-time)requiredqueuebooleanoptionalApproving puts it in the profile’s queue.
decisionstringoptionaldecidedBystringoptionaldecidedAtstring (date-time)optionalnotestringoptionalWhy it was rejected.
recyclingobjectoptionalPresent once recycling was turned on.
recycling
activebooleanrequiredeveryintegerrequiredunitstringrequiredstartAtstring (date-time)optionalmaxCopiesintegeroptionaluntilstring (date-time)optionalvariationsstring[]optionaltimezonestringoptionalcopiesintegerrequiredCopies created so far.
nextAtstring (date-time)optionalWhen the next copy goes out; absent once it stopped.
lastCopyIdstringoptionalThe latest copy, a post of its own.
recycledFromstringoptionalOn a recycled copy: the original post.
createdAtstring (date-time)requiredupdatedAtstring (date-time)required
curl -X POST "https://api.usecrier.com/v1/posts/pst_7q1w0e/cancel" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e/cancel', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/posts/pst_7q1w0e/cancel",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/posts/{id}/reviewApprove or reject a post
Only for posts in pending_approval, by owners, admins or an API key. Approving schedules it for its date, puts it in the queue if it asked for one, or publishes it now if its date already passed. Rejecting returns it to draft with the note and sends post.rejected.
Parameters
idstringrequired
Body
decisionstringrequiredapproveschedules it (or publishes it now if its date passed);rejectreturns it to draft.notestringoptionalWhy, for whoever wrote it. Shown with the draft after a rejection.
Response 200
data
idstringrequiredcontentstringrequiredmediaobject[]requiredmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
targetsobject[]requiredtargets
accountIdstringrequiredplatformstringrequiredcontentstringoptionalmediaobject[]optionalmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
statusstringrequiredurlstring (uri)optionalThe live post, once published.
errorstringoptional
statusstringrequiredscheduledForstring (date-time)optionalapprovalobjectoptionalPresent once the post went through review.
approval
requestedBystringoptionalUser who asked for it; absent when an API key did.
requestedAtstring (date-time)requiredqueuebooleanoptionalApproving puts it in the profile’s queue.
decisionstringoptionaldecidedBystringoptionaldecidedAtstring (date-time)optionalnotestringoptionalWhy it was rejected.
recyclingobjectoptionalPresent once recycling was turned on.
recycling
activebooleanrequiredeveryintegerrequiredunitstringrequiredstartAtstring (date-time)optionalmaxCopiesintegeroptionaluntilstring (date-time)optionalvariationsstring[]optionaltimezonestringoptionalcopiesintegerrequiredCopies created so far.
nextAtstring (date-time)optionalWhen the next copy goes out; absent once it stopped.
lastCopyIdstringoptionalThe latest copy, a post of its own.
recycledFromstringoptionalOn a recycled copy: the original post.
createdAtstring (date-time)requiredupdatedAtstring (date-time)required
curl -X POST "https://api.usecrier.com/v1/posts/pst_7q1w0e/review" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e/review', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/posts/pst_7q1w0e/review",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/posts/{id}/recyclingRecycle a post
Posts it again every every weeks or months as a new post (recycledFrom points back), until maxCopies or until. YouTube and TikTok targets are left out of the copies, and each account can have up to 10 posts recycling. Sending it again changes the rule and keeps the count.
Parameters
idstringrequired
Body
everyintegerrequiredHow many units between copies.
unitstringrequiredweekormonth.startAtstring (date-time)optionalWhen the first copy goes out. Defaults to one interval after the post’s date; for an old post, the next date of that series, at the same time of day.
maxCopiesintegeroptionalStop after this many copies.
untilstring (date-time)optionalStop after this date.
variationsstring[]optionalTexts used in turn instead of the post’s text. A target’s own text still wins. Recommended for X and Pinterest, which flag repeats.
timezonestringoptionalIANA time zone (e.g.
Europe/Madrid) the interval is counted in, so copies keep their local time when the clocks change. UTC by default.
Response 200
data
idstringrequiredcontentstringrequiredmediaobject[]requiredmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
targetsobject[]requiredtargets
accountIdstringrequiredplatformstringrequiredcontentstringoptionalmediaobject[]optionalmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
statusstringrequiredurlstring (uri)optionalThe live post, once published.
errorstringoptional
statusstringrequiredscheduledForstring (date-time)optionalapprovalobjectoptionalPresent once the post went through review.
approval
requestedBystringoptionalUser who asked for it; absent when an API key did.
requestedAtstring (date-time)requiredqueuebooleanoptionalApproving puts it in the profile’s queue.
decisionstringoptionaldecidedBystringoptionaldecidedAtstring (date-time)optionalnotestringoptionalWhy it was rejected.
recyclingobjectoptionalPresent once recycling was turned on.
recycling
activebooleanrequiredeveryintegerrequiredunitstringrequiredstartAtstring (date-time)optionalmaxCopiesintegeroptionaluntilstring (date-time)optionalvariationsstring[]optionaltimezonestringoptionalcopiesintegerrequiredCopies created so far.
nextAtstring (date-time)optionalWhen the next copy goes out; absent once it stopped.
lastCopyIdstringoptionalThe latest copy, a post of its own.
recycledFromstringoptionalOn a recycled copy: the original post.
createdAtstring (date-time)requiredupdatedAtstring (date-time)required
curl -X PUT "https://api.usecrier.com/v1/posts/pst_7q1w0e/recycling" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e/recycling', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.put(
"https://api.usecrier.com/v1/posts/pst_7q1w0e/recycling",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/posts/{id}/recyclingStop recycling a post
Copies already created stay as they are.
Parameters
idstringrequired
Response 200
data
idstringrequiredcontentstringrequiredmediaobject[]requiredmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
targetsobject[]requiredtargets
accountIdstringrequiredplatformstringrequiredcontentstringoptionalmediaobject[]optionalmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
statusstringrequiredurlstring (uri)optionalThe live post, once published.
errorstringoptional
statusstringrequiredscheduledForstring (date-time)optionalapprovalobjectoptionalPresent once the post went through review.
approval
requestedBystringoptionalUser who asked for it; absent when an API key did.
requestedAtstring (date-time)requiredqueuebooleanoptionalApproving puts it in the profile’s queue.
decisionstringoptionaldecidedBystringoptionaldecidedAtstring (date-time)optionalnotestringoptionalWhy it was rejected.
recyclingobjectoptionalPresent once recycling was turned on.
recycling
activebooleanrequiredeveryintegerrequiredunitstringrequiredstartAtstring (date-time)optionalmaxCopiesintegeroptionaluntilstring (date-time)optionalvariationsstring[]optionaltimezonestringoptionalcopiesintegerrequiredCopies created so far.
nextAtstring (date-time)optionalWhen the next copy goes out; absent once it stopped.
lastCopyIdstringoptionalThe latest copy, a post of its own.
recycledFromstringoptionalOn a recycled copy: the original post.
createdAtstring (date-time)requiredupdatedAtstring (date-time)required
curl -X DELETE "https://api.usecrier.com/v1/posts/pst_7q1w0e/recycling" \
-H "Authorization: Bearer $CRIER_API_KEY"await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e/recycling', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});import os, requests
requests.delete(
"https://api.usecrier.com/v1/posts/pst_7q1w0e/recycling",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)/v1/posts/{id}/retryRetry the failed targets
Parameters
idstringrequired
Response 200
data
idstringrequiredcontentstringrequiredmediaobject[]requiredmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
targetsobject[]requiredtargets
accountIdstringrequiredplatformstringrequiredcontentstringoptionalmediaobject[]optionalmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
statusstringrequiredurlstring (uri)optionalThe live post, once published.
errorstringoptional
statusstringrequiredscheduledForstring (date-time)optionalapprovalobjectoptionalPresent once the post went through review.
approval
requestedBystringoptionalUser who asked for it; absent when an API key did.
requestedAtstring (date-time)requiredqueuebooleanoptionalApproving puts it in the profile’s queue.
decisionstringoptionaldecidedBystringoptionaldecidedAtstring (date-time)optionalnotestringoptionalWhy it was rejected.
recyclingobjectoptionalPresent once recycling was turned on.
recycling
activebooleanrequiredeveryintegerrequiredunitstringrequiredstartAtstring (date-time)optionalmaxCopiesintegeroptionaluntilstring (date-time)optionalvariationsstring[]optionaltimezonestringoptionalcopiesintegerrequiredCopies created so far.
nextAtstring (date-time)optionalWhen the next copy goes out; absent once it stopped.
lastCopyIdstringoptionalThe latest copy, a post of its own.
recycledFromstringoptionalOn a recycled copy: the original post.
createdAtstring (date-time)requiredupdatedAtstring (date-time)required
curl -X POST "https://api.usecrier.com/v1/posts/pst_7q1w0e/retry" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e/retry', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/posts/pst_7q1w0e/retry",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/posts/{id}/unpublishTake a published post down
From every network, or only from accountId.
Parameters
idstringrequired
Body
accountIdstringoptional
Response 200
data
idstringrequiredcontentstringrequiredmediaobject[]requiredmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
targetsobject[]requiredtargets
accountIdstringrequiredplatformstringrequiredcontentstringoptionalmediaobject[]optionalmedia
typestringrequiredurlstring (uri)requiredaltTextstringoptional
statusstringrequiredurlstring (uri)optionalThe live post, once published.
errorstringoptional
statusstringrequiredscheduledForstring (date-time)optionalapprovalobjectoptionalPresent once the post went through review.
approval
requestedBystringoptionalUser who asked for it; absent when an API key did.
requestedAtstring (date-time)requiredqueuebooleanoptionalApproving puts it in the profile’s queue.
decisionstringoptionaldecidedBystringoptionaldecidedAtstring (date-time)optionalnotestringoptionalWhy it was rejected.
recyclingobjectoptionalPresent once recycling was turned on.
recycling
activebooleanrequiredeveryintegerrequiredunitstringrequiredstartAtstring (date-time)optionalmaxCopiesintegeroptionaluntilstring (date-time)optionalvariationsstring[]optionaltimezonestringoptionalcopiesintegerrequiredCopies created so far.
nextAtstring (date-time)optionalWhen the next copy goes out; absent once it stopped.
lastCopyIdstringoptionalThe latest copy, a post of its own.
recycledFromstringoptionalOn a recycled copy: the original post.
createdAtstring (date-time)requiredupdatedAtstring (date-time)required
curl -X POST "https://api.usecrier.com/v1/posts/pst_7q1w0e/unpublish" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "acc_3k9x2m"
}'const res = await fetch('https://api.usecrier.com/v1/posts/pst_7q1w0e/unpublish', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"accountId": "acc_3k9x2m"
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/posts/pst_7q1w0e/unpublish",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
json={
"accountId": "acc_3k9x2m"
},
)
data = res.json()["data"]Media
Upload images and videos to Crier before posting them.
/v1/media/upload-urlGet an upload URL
JPEG, PNG, WebP and GIF up to 20 MB; MP4, MOV and WebM up to 1 GB. PUT the file to uploadUrl, then post publicUrl.
Body
filenamestringrequiredcontentTypestringrequiredsizeintegerrequired
Response 200
data
uploadUrlstring (uri)requiredPre-signed URL: PUT the file there with the same Content-Type.
publicUrlstring (uri)requiredUse it in a post's media once uploaded.
kindstringrequiredexpiresInintegerrequiredSeconds the upload URL stays valid.
curl -X POST "https://api.usecrier.com/v1/media/upload-url" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "autumn.mp4",
"contentType": "video/mp4",
"size": 48211234
}'const res = await fetch('https://api.usecrier.com/v1/media/upload-url', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"filename": "autumn.mp4",
"contentType": "video/mp4",
"size": 48211234
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/media/upload-url",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
json={
"filename": "autumn.mp4",
"contentType": "video/mp4",
"size": 48211234
},
)
data = res.json()["data"]Inbox
Direct messages, comments and reviews of a profile’s accounts. Lists take the profile; actions take the account the item belongs to.
/v1/inbox/conversationsList conversations
Direct messages on Facebook, Instagram, X, Bluesky, Reddit and Telegram, most recent first.
Parameters
profileIdstringrequiredaccountIdstringoptionalstatusstringoptionalcursorstringoptionalnextCursor of the previous page.
limitintegeroptional
Response 200
data
itemsobject[]requireditems
idstringrequiredOpaque conversation id.
accountIdstringrequiredplatformstringrequiredparticipantobjectrequiredparticipant
namestringoptionalusernamestringoptionalpicturestring (uri)optional
lastMessagestringoptionalupdatedAtstring (date-time)optionalstatusstringrequiredunreadCountintegerrequiredurlstring (uri)optionalOpens the conversation on the network.
nextCursorstring | nullrequiredSend it as cursor for the next page; null on the last one.
curl "https://api.usecrier.com/v1/inbox/conversations" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/inbox/conversations', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/inbox/conversations",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/inbox/conversations/{id}/messagesList the messages of a conversation
Parameters
idstringrequiredaccountIdstringrequiredThe account the item belongs to.
cursorstringoptionalnextCursor of the previous page.
Response 200
data
itemsobject[]requireditems
idstringrequireddirectionstringrequiredtextstringrequiredsenderNamestringoptionalcreatedAtstring (date-time)requiredattachmentsobject[]requiredattachments
typestringrequiredurlstring (uri)optionalnamestringoptional
deliveryStatusstringoptionaldeletedbooleanrequired
nextCursorstring | nullrequiredSend it as cursor for the next page; null on the last one.
curl "https://api.usecrier.com/v1/inbox/conversations/key_2b4n6m/messages" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/inbox/conversations/key_2b4n6m/messages', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/inbox/conversations/key_2b4n6m/messages",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/inbox/conversations/{id}/messagesSend a message
Text, an attachment or both. Meta only lets a page answer within 24 hours of the person’s last message.
Parameters
idstringrequired
Body
accountIdstringrequiredThe account the item belongs to.
textstringoptionalattachmentUrlstring (uri)optionalA public https URL (for example from POST /v1/media/upload-url).
attachmentTypestringoptional
Response 204
No content
curl -X POST "https://api.usecrier.com/v1/inbox/conversations/key_2b4n6m/messages" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/inbox/conversations/key_2b4n6m/messages', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/inbox/conversations/key_2b4n6m/messages",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/inbox/conversations/{id}/readMark a conversation as read
Parameters
idstringrequired
Body
accountIdstringrequiredThe account the item belongs to.
Response 204
No content
curl -X POST "https://api.usecrier.com/v1/inbox/conversations/key_2b4n6m/read" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/inbox/conversations/key_2b4n6m/read', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/inbox/conversations/key_2b4n6m/read",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/inbox/conversations/{id}Archive or reopen a conversation
Parameters
idstringrequired
Body
accountIdstringrequiredThe account the item belongs to.
statusstringrequired
Response 204
No content
curl -X PATCH "https://api.usecrier.com/v1/inbox/conversations/key_2b4n6m" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/inbox/conversations/key_2b4n6m', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.patch(
"https://api.usecrier.com/v1/inbox/conversations/key_2b4n6m",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/inbox/postsList posts with comments
Recent posts of the profile’s accounts with their comment counts, including posts published outside Crier.
Parameters
profileIdstringrequiredaccountIdstringoptionalcursorstringoptionalnextCursor of the previous page.
limitintegeroptional
Response 200
data
itemsobject[]requireditems
idstringrequiredOpaque post id for the comment endpoints.
accountIdstringrequiredplatformstringrequiredcontentstringrequiredpicturestring (uri)optionalurlstring (uri)optionalcreatedAtstring (date-time)optionalcommentCountintegerrequiredlikeCountintegerrequired
nextCursorstring | nullrequiredSend it as cursor for the next page; null on the last one.
curl "https://api.usecrier.com/v1/inbox/posts" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/inbox/posts', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/inbox/posts",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/inbox/posts/{id}/commentsList the comments of a post
Parameters
idstringrequiredaccountIdstringrequiredThe account the item belongs to.
cursorstringoptionalnextCursor of the previous page.
Response 200
data
itemsobject[]requireditems
idstringrequiredOpaque comment id.
textstringrequiredauthorobjectrequiredauthor
namestringoptionalusernamestringoptionalpicturestring (uri)optionalisOwnerbooleanrequiredWritten by the connected account.
createdAtstring (date-time)optionallikeCountintegerrequiredreplyCountintegerrequiredurlstring (uri)optionalcanobjectrequiredWhat this network allows on it.
can
replybooleanrequireddeletebooleanrequiredhidebooleanrequiredlikebooleanrequired
hiddenbooleanrequiredlikedbooleanrequiredrepliesobject[]requiredreplies
idstringrequiredOpaque comment id.
textstringrequiredauthorobjectrequiredauthor
namestringoptionalusernamestringoptionalpicturestring (uri)optionalisOwnerbooleanrequiredWritten by the connected account.
createdAtstring (date-time)optionallikeCountintegerrequiredreplyCountintegerrequiredurlstring (uri)optionalcanobjectrequiredWhat this network allows on it.
can
replybooleanrequireddeletebooleanrequiredhidebooleanrequiredlikebooleanrequired
hiddenbooleanrequiredlikedbooleanrequired
nextCursorstring | nullrequiredSend it as cursor for the next page; null on the last one.
curl "https://api.usecrier.com/v1/inbox/posts/key_2b4n6m/comments" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/inbox/posts/key_2b4n6m/comments', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/inbox/posts/key_2b4n6m/comments",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/inbox/posts/{id}/commentsComment or reply to a comment
Parameters
idstringrequired
Body
accountIdstringrequiredThe account the item belongs to.
textstringrequiredcommentIdstringoptionalReply under this comment; omit to comment on the post.
Response 204
No content
curl -X POST "https://api.usecrier.com/v1/inbox/posts/key_2b4n6m/comments" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/inbox/posts/key_2b4n6m/comments', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/inbox/posts/key_2b4n6m/comments",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/inbox/posts/{id}/comments/{commentId}Hide or like a comment
Each comment says in can what its network allows.
Parameters
idstringrequiredcommentIdstringrequired
Body
accountIdstringrequiredThe account the item belongs to.
hiddenbooleanoptionallikedbooleanoptional
Response 204
No content
curl -X PATCH "https://api.usecrier.com/v1/inbox/posts/key_2b4n6m/comments/{commentId}" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/inbox/posts/key_2b4n6m/comments/{commentId}', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.patch(
"https://api.usecrier.com/v1/inbox/posts/key_2b4n6m/comments/{commentId}",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/inbox/posts/{id}/comments/{commentId}Delete a comment
Parameters
idstringrequiredcommentIdstringrequiredaccountIdstringrequiredThe account the item belongs to.
Response 204
No content
curl -X DELETE "https://api.usecrier.com/v1/inbox/posts/key_2b4n6m/comments/{commentId}" \
-H "Authorization: Bearer $CRIER_API_KEY"await fetch('https://api.usecrier.com/v1/inbox/posts/key_2b4n6m/comments/{commentId}', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});import os, requests
requests.delete(
"https://api.usecrier.com/v1/inbox/posts/key_2b4n6m/comments/{commentId}",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)/v1/inbox/reviewsList reviews
Google Business and Facebook reviews, with their total and average rating.
Parameters
profileIdstringrequiredaccountIdstringoptionalcursorstringoptionalnextCursor of the previous page.
limitintegeroptionalhasReplystringoptionalOnly reviews with (true) or without (false) a reply.
Response 200
data
itemsobject[]requireditems
idstringrequiredOpaque review id.
accountIdstringrequiredplatformstringrequiredreviewerobjectrequiredreviewer
namestringoptionalusernamestringoptionalpicturestring (uri)optional
ratinginteger | nullrequired1 to 5; null on Facebook, which recommends instead.
recommendsbooleanoptionaltextstringrequiredcreatedAtstring (date-time)optionalreplyobject | nullrequiredreply
textstringrequiredcreatedAtstring (date-time)optional
urlstring (uri)optionallocationstringoptionalGoogle Business location.
nextCursorstring | nullrequiredSend it as cursor for the next page; null on the last one.
summaryobjectrequiredsummary
totalintegerrequiredaverageRatingnumber | nullrequired
curl "https://api.usecrier.com/v1/inbox/reviews" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/inbox/reviews', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/inbox/reviews",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/inbox/reviews/{id}/replyReply to a review
Parameters
idstringrequired
Body
accountIdstringrequiredThe account the item belongs to.
textstringrequired
Response 204
No content
curl -X POST "https://api.usecrier.com/v1/inbox/reviews/key_2b4n6m/reply" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/inbox/reviews/key_2b4n6m/reply', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/inbox/reviews/key_2b4n6m/reply",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/inbox/reviews/{id}/replyDelete a review reply
Google Business only.
Parameters
idstringrequiredaccountIdstringrequiredThe account the item belongs to.
Response 204
No content
curl -X DELETE "https://api.usecrier.com/v1/inbox/reviews/key_2b4n6m/reply" \
-H "Authorization: Bearer $CRIER_API_KEY"await fetch('https://api.usecrier.com/v1/inbox/reviews/key_2b4n6m/reply', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});import os, requests
requests.delete(
"https://api.usecrier.com/v1/inbox/reviews/key_2b4n6m/reply",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)Automations
Comment-to-DM: when someone comments a keyword, answer with a private message (Instagram, Facebook) or a public reply (every network).
/v1/automationsList automations
Parameters
profileIdstringrequiredaccountIdstringoptional
Response 200
data []
idstringrequiredaccountIdstringrequiredplatformstringrequirednamestringrequiredtriggerstringrequiredpostIdstring | nullrequiredinboxPostIdstring | nullrequiredkeywordsstring[]requiredmatchModestringrequiredexcludeKeywordsstring[]requireddmMessagestringoptionalbuttonsobject[]requiredbuttons
typestringrequiredtitlestringrequiredurlstring (uri)optionalpayloadstringoptional
commentReplystringoptionaldmDelaySecondsintegeroptionalrepeatstringrequiredlikeCommentbooleanrequiredhideCommentbooleanrequiredactivebooleanrequiredstatsobjectrequiredstats
triggeredintegerrequireddmsSentintegerrequireddmsFailedintegerrequireduniqueContactsintegerrequiredlinkClicksintegerrequired
createdAtstring (date-time)optional
curl "https://api.usecrier.com/v1/automations" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/automations', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/automations",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/automationsCreate an automation
On Instagram and Facebook it sends dmMessage (with up to 3 buttons) to whoever comments a keyword; on TikTok, Threads, LinkedIn and YouTube it posts commentReply. Without a post it watches every post of the account.
Body
namestringrequiredtriggerstringoptionalstory_reply: replies to an Instagram story.postIdstring | nulloptionalA Crier post to watch.
inboxPostIdstring | nulloptionalOr a post as GET /v1/inbox/posts lists it. Neither: every post.
keywordsstring[]optionalEmpty: any comment fires it.
matchModestringoptionalexcludeKeywordsstring[]optionaldmMessagestringoptionalPrivate message to the commenter. Instagram and Facebook only, required there.
buttonsobject[]optionalUp to 3 buttons under the DM.
buttons
typestringrequiredtitlestringrequiredurlstring (uri)optionalpayloadstringoptional
commentReplystringoptionalPublic reply to the comment. Required on TikTok, Threads, LinkedIn and YouTube.
dmDelaySecondsintegeroptionalrepeatstringoptionalonce: one DM per person.likeCommentbooleanoptionalhideCommentbooleanoptionalactivebooleanoptionalaccountIdstringrequiredInstagram, Facebook, TikTok, Threads, LinkedIn or YouTube account.
Response 201
data
idstringrequiredaccountIdstringrequiredplatformstringrequirednamestringrequiredtriggerstringrequiredpostIdstring | nullrequiredinboxPostIdstring | nullrequiredkeywordsstring[]requiredmatchModestringrequiredexcludeKeywordsstring[]requireddmMessagestringoptionalbuttonsobject[]requiredbuttons
typestringrequiredtitlestringrequiredurlstring (uri)optionalpayloadstringoptional
commentReplystringoptionaldmDelaySecondsintegeroptionalrepeatstringrequiredlikeCommentbooleanrequiredhideCommentbooleanrequiredactivebooleanrequiredstatsobjectrequiredstats
triggeredintegerrequireddmsSentintegerrequireddmsFailedintegerrequireduniqueContactsintegerrequiredlinkClicksintegerrequired
createdAtstring (date-time)optional
curl -X POST "https://api.usecrier.com/v1/automations" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/automations', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/automations",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/automations/{id}Get an automation
Parameters
idstringrequired
Response 200
data
idstringrequiredaccountIdstringrequiredplatformstringrequirednamestringrequiredtriggerstringrequiredpostIdstring | nullrequiredinboxPostIdstring | nullrequiredkeywordsstring[]requiredmatchModestringrequiredexcludeKeywordsstring[]requireddmMessagestringoptionalbuttonsobject[]requiredbuttons
typestringrequiredtitlestringrequiredurlstring (uri)optionalpayloadstringoptional
commentReplystringoptionaldmDelaySecondsintegeroptionalrepeatstringrequiredlikeCommentbooleanrequiredhideCommentbooleanrequiredactivebooleanrequiredstatsobjectrequiredstats
triggeredintegerrequireddmsSentintegerrequireddmsFailedintegerrequireduniqueContactsintegerrequiredlinkClicksintegerrequired
createdAtstring (date-time)optional
curl "https://api.usecrier.com/v1/automations/key_2b4n6m" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/automations/key_2b4n6m', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/automations/key_2b4n6m",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/automations/{id}Update or pause an automation
Fields you leave out keep their value. active: false pauses it.
Parameters
idstringrequired
Body
namestringoptionaltriggerstringoptionalstory_reply: replies to an Instagram story.postIdstring | nulloptionalA Crier post to watch.
inboxPostIdstring | nulloptionalOr a post as GET /v1/inbox/posts lists it. Neither: every post.
keywordsstring[]optionalEmpty: any comment fires it.
matchModestringoptionalexcludeKeywordsstring[]optionaldmMessagestringoptionalPrivate message to the commenter. Instagram and Facebook only, required there.
buttonsobject[]optionalUp to 3 buttons under the DM.
buttons
typestringrequiredtitlestringrequiredurlstring (uri)optionalpayloadstringoptional
commentReplystringoptionalPublic reply to the comment. Required on TikTok, Threads, LinkedIn and YouTube.
dmDelaySecondsintegeroptionalrepeatstringoptionalonce: one DM per person.likeCommentbooleanoptionalhideCommentbooleanoptionalactivebooleanoptional
Response 200
data
idstringrequiredaccountIdstringrequiredplatformstringrequirednamestringrequiredtriggerstringrequiredpostIdstring | nullrequiredinboxPostIdstring | nullrequiredkeywordsstring[]requiredmatchModestringrequiredexcludeKeywordsstring[]requireddmMessagestringoptionalbuttonsobject[]requiredbuttons
typestringrequiredtitlestringrequiredurlstring (uri)optionalpayloadstringoptional
commentReplystringoptionaldmDelaySecondsintegeroptionalrepeatstringrequiredlikeCommentbooleanrequiredhideCommentbooleanrequiredactivebooleanrequiredstatsobjectrequiredstats
triggeredintegerrequireddmsSentintegerrequireddmsFailedintegerrequireduniqueContactsintegerrequiredlinkClicksintegerrequired
createdAtstring (date-time)optional
curl -X PATCH "https://api.usecrier.com/v1/automations/key_2b4n6m" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/automations/key_2b4n6m', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.patch(
"https://api.usecrier.com/v1/automations/key_2b4n6m",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/automations/{id}Delete an automation
Parameters
idstringrequired
Response 204
No content
curl -X DELETE "https://api.usecrier.com/v1/automations/key_2b4n6m" \
-H "Authorization: Bearer $CRIER_API_KEY"await fetch('https://api.usecrier.com/v1/automations/key_2b4n6m', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});import os, requests
requests.delete(
"https://api.usecrier.com/v1/automations/key_2b4n6m",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)/v1/automations/{id}/logsWhat an automation did
Every comment that fired it, newest first, with the DM outcome.
Parameters
idstringrequiredskipintegeroptionallimitintegeroptional
Response 200
data
itemsobject[]requireditems
idstringrequiredcommenterobjectrequiredcommenter
namestringoptionalusernamestringoptional
commentTextstringoptionalstatusstringrequirederrorstringoptionalreplyStatusstringoptionalclickedbooleanrequiredcreatedAtstring (date-time)required
totalintegerrequired
curl "https://api.usecrier.com/v1/automations/key_2b4n6m/logs" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/automations/key_2b4n6m/logs', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/automations/key_2b4n6m/logs",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]Analytics
Followers, daily totals, best times to post and top posts, per profile or per account.
/v1/analytics/followersFollowers and growth
Current followers, growth over the period and the daily history of each account. Refreshed once a day.
Parameters
profileIdstringrequiredaccountIdstringoptionalOnly this account; the whole profile otherwise.
fromstringoptionalFirst day (YYYY-MM-DD). Defaults to 30 days ago.
tostringoptionalLast day (YYYY-MM-DD). Defaults to today.
Response 200
data []
accountIdstringrequiredplatformstringrequiredusernamestringoptionalfollowersintegerrequiredgrowthintegerrequiredChange over the period.
growthPercentnumberrequiredhistoryobject[]requiredhistory
datestringrequiredYYYY-MM-DD
followersintegerrequired
curl "https://api.usecrier.com/v1/analytics/followers" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/analytics/followers', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/analytics/followers",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/analytics/dailyDaily totals
Posts and engagement per day (counted on the day it arrived), and totals per network.
Parameters
profileIdstringrequiredaccountIdstringoptionalOnly this account; the whole profile otherwise.
fromstringoptionalFirst day (YYYY-MM-DD). Defaults to 30 days ago.
tostringoptionalLast day (YYYY-MM-DD). Defaults to today.
Response 200
data
daysobject[]requireddays
datestringrequiredYYYY-MM-DD
postsintegerrequiredmetricsobjectrequiredmetrics
impressionsintegerrequiredreachintegerrequiredviewsintegerrequiredlikesintegerrequiredcommentsintegerrequiredsharesintegerrequiredsavesintegerrequiredclicksintegerrequiredengagementRatenumberrequiredPercentage: interactions over impressions (or reach).
byPlatformobject[]requiredbyPlatform
platformstringrequiredpostsintegerrequiredmetricsobjectrequiredmetrics
impressionsintegerrequiredreachintegerrequiredviewsintegerrequiredlikesintegerrequiredcommentsintegerrequiredsharesintegerrequiredsavesintegerrequiredclicksintegerrequiredengagementRatenumberrequiredPercentage: interactions over impressions (or reach).
curl "https://api.usecrier.com/v1/analytics/daily" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/analytics/daily', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/analytics/daily",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/analytics/best-timesBest times to post
Average engagement per weekday and hour, from the account’s published posts.
Parameters
profileIdstringrequiredaccountIdstringoptionalOnly this account; the whole profile otherwise.
Response 200
data []
dayOfWeekintegerrequired0 = Sunday … 6 = Saturday
hourintegerrequiredHour in UTC
avgEngagementnumberrequiredpostsintegerrequired
curl "https://api.usecrier.com/v1/analytics/best-times" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/analytics/best-times', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/analytics/best-times",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/analytics/top-postsTop posts
Posts of the period by engagement (or date), including those published outside Crier.
Parameters
profileIdstringrequiredaccountIdstringoptionalOnly this account; the whole profile otherwise.
fromstringoptionalFirst day (YYYY-MM-DD). Defaults to 30 days ago.
tostringoptionalLast day (YYYY-MM-DD). Defaults to today.
sortBystringoptionallimitintegeroptional
Response 200
data []
postIdstring | nullrequiredThe Crier post, when it was published through Crier.
accountIdstring | nullrequiredplatformstringrequiredcontentstringrequiredpublishedAtstring (date-time)optionalurlstring (uri)optionalthumbnailUrlstring (uri)optionalmetricsobjectrequiredmetrics
impressionsintegerrequiredreachintegerrequiredviewsintegerrequiredlikesintegerrequiredcommentsintegerrequiredsharesintegerrequiredsavesintegerrequiredclicksintegerrequiredengagementRatenumberrequiredPercentage: interactions over impressions (or reach).
externalbooleanrequiredPublished outside Crier.
curl "https://api.usecrier.com/v1/analytics/top-posts" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/analytics/top-posts', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/analytics/top-posts",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]Billing
A prepaid balance: connected accounts beyond the free ones are charged day by day and usage (X API, messages) as it happens. Topping it up happens in the dashboard.
/v1/billingGet the balance
Balance, connected accounts and what they cost. With the balance used up, connecting beyond the free accounts, and publishing or sending from accounts beyond them or on X, answer 402.
Response 200
data
enabledbooleanrequiredFalse while billing is not available: nothing is charged or limited.
balancenumberrequiredPrepaid balance in cents (up to three decimals). Negative when charges outran it.
currencystringrequiredconnectedAccountsintegerrequiredfreeAccountsintegerrequiredmonthlyEstimateintegerrequiredMonthly price of the accounts connected now, in cents. It is charged day by day.
dailyEstimatenumberrequiredWhat those accounts cost today, in cents (up to three decimals).
daysLeftinteger | nullrequiredWhole days the balance covers at that cost; null when nothing is charged daily.
linesobject[]requiredlines
fromintegerrequiredtointeger | nullrequiredaccountsintegerrequiredunitAmountintegerrequiredCents per account and month.
amountintegerrequired
canConnectMorebooleanrequiredWhether one more account can be connected right now.
blockedbooleanrequiredThe balance is used up: accounts beyond the free ones, and X accounts, cannot publish or send until it is topped up.
cardobjectoptionalThe saved payment method, for automatic recharges.
card
brandstringrequiredCard brand (
visa,mastercard…) or another saved method (link,sepa_debit).last4stringoptionalexpMonthintegeroptionalexpYearintegeroptional
autoRechargeobjectoptionalautoRecharge
enabledbooleanrequiredthresholdintegerrequiredRecharge when the balance falls below this, in cents.
amountintegerrequiredWhat each recharge adds, in cents.
monthlyLimitintegerrequiredMost that automatic recharges add in a calendar month, in cents.
autoRechargeErrorobjectoptionalWhy the last automatic recharge failed; it switched itself off.
autoRechargeError
atstring (date-time)requiredmessagestringrequired
autoRechargedThisMonthintegerrequiredAdded by automatic recharges this calendar month, in cents.
topUpobjectrequiredAllowed top-up amounts, in cents.
topUp
minintegerrequiredmaxintegerrequired
hasPortalbooleanrequiredWhether the billing portal (invoices, payment method) is available.
curl "https://api.usecrier.com/v1/billing" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/billing', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/billing",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/billing/movementsList balance movements
Top-ups and charges, newest first.
Parameters
limitintegeroptional
Response 200
data []
idstringrequiredkindstringrequiredamountnumberrequiredCents (up to three decimals): positive adds, negative debits.
atstring (date-time)requireddaystringoptionalUTC day (YYYY-MM-DD) a charge covers.
accountsintegeroptionalAccounts a day was charged for.
familystringoptionalUsage family of a usage charge.
curl "https://api.usecrier.com/v1/billing/movements" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/billing/movements', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/billing/movements",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/billing/top-upTop up the balance
Dashboard onlyOpens a payment page. The balance grows once the payment succeeds; the card is saved for automatic recharges.
Body
amountintegerrequiredBalance to add, in cents (taxes, if any, on top). Limits come with GET /v1/billing.
successUrlstring (uri)requiredDashboard page to come back to after paying.
cancelUrlstring (uri)requiredDashboard page to come back to if the user leaves Checkout.
Response 200
data
urlstring (uri)requiredSend the user here.
curl -X POST "https://api.usecrier.com/v1/billing/top-up" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/billing/top-up', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/billing/top-up",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/billing/auto-rechargeSet automatic recharges
Dashboard onlyTops up the saved card when the balance falls below the threshold, up to a monthly limit. Needs one top-up first.
Body
enabledbooleanrequiredthresholdintegerrequiredRecharge when the balance falls below this, in cents.
amountintegerrequiredWhat each recharge adds, in cents.
monthlyLimitintegerrequiredMost that automatic recharges may add in a calendar month, in cents.
Response 200
data
enabledbooleanrequiredFalse while billing is not available: nothing is charged or limited.
balancenumberrequiredPrepaid balance in cents (up to three decimals). Negative when charges outran it.
currencystringrequiredconnectedAccountsintegerrequiredfreeAccountsintegerrequiredmonthlyEstimateintegerrequiredMonthly price of the accounts connected now, in cents. It is charged day by day.
dailyEstimatenumberrequiredWhat those accounts cost today, in cents (up to three decimals).
daysLeftinteger | nullrequiredWhole days the balance covers at that cost; null when nothing is charged daily.
linesobject[]requiredlines
fromintegerrequiredtointeger | nullrequiredaccountsintegerrequiredunitAmountintegerrequiredCents per account and month.
amountintegerrequired
canConnectMorebooleanrequiredWhether one more account can be connected right now.
blockedbooleanrequiredThe balance is used up: accounts beyond the free ones, and X accounts, cannot publish or send until it is topped up.
cardobjectoptionalThe saved payment method, for automatic recharges.
card
brandstringrequiredCard brand (
visa,mastercard…) or another saved method (link,sepa_debit).last4stringoptionalexpMonthintegeroptionalexpYearintegeroptional
autoRechargeobjectoptionalautoRecharge
enabledbooleanrequiredthresholdintegerrequiredRecharge when the balance falls below this, in cents.
amountintegerrequiredWhat each recharge adds, in cents.
monthlyLimitintegerrequiredMost that automatic recharges add in a calendar month, in cents.
autoRechargeErrorobjectoptionalWhy the last automatic recharge failed; it switched itself off.
autoRechargeError
atstring (date-time)requiredmessagestringrequired
autoRechargedThisMonthintegerrequiredAdded by automatic recharges this calendar month, in cents.
topUpobjectrequiredAllowed top-up amounts, in cents.
topUp
minintegerrequiredmaxintegerrequired
hasPortalbooleanrequiredWhether the billing portal (invoices, payment method) is available.
curl -X PUT "https://api.usecrier.com/v1/billing/auto-recharge" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/billing/auto-recharge', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.put(
"https://api.usecrier.com/v1/billing/auto-recharge",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/billing/portalOpen the billing portal
Dashboard onlyInvoices and the saved payment method.
Body
returnUrlstring (uri)requiredDashboard page to come back to.
Response 200
data
urlstring (uri)requiredSend the user here.
curl -X POST "https://api.usecrier.com/v1/billing/portal" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/billing/portal', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/billing/portal",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]Webhooks
Receive Crier events at your HTTPS endpoint.
/v1/webhook-endpointGet the webhook endpoint
Response 200
data
urlstring (uri)requiredeventsstring[]requiredcreatedAtstring (date-time)requiredupdatedAtstring (date-time)required
curl "https://api.usecrier.com/v1/webhook-endpoint" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/webhook-endpoint', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/webhook-endpoint",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/webhook-endpointSet the webhook endpoint
Omit events to receive all of them. The signing secret is returned only the first time.
Body
urlstring (starts_with)requiredeventsstring[]optional
Response 200
data
endpointobjectrequiredendpoint
urlstring (uri)requiredeventsstring[]requiredcreatedAtstring (date-time)requiredupdatedAtstring (date-time)required
secretstringoptionalSigning secret, returned only when the endpoint is created.
curl -X PUT "https://api.usecrier.com/v1/webhook-endpoint" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://app.acme.com/webhooks/crier"
}'const res = await fetch('https://api.usecrier.com/v1/webhook-endpoint', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"url": "https://app.acme.com/webhooks/crier"
}),
});
const { data } = await res.json();import os, requests
res = requests.put(
"https://api.usecrier.com/v1/webhook-endpoint",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
json={
"url": "https://app.acme.com/webhooks/crier"
},
)
data = res.json()["data"]/v1/webhook-endpointDelete the webhook endpoint
Response 204
No content
curl -X DELETE "https://api.usecrier.com/v1/webhook-endpoint" \
-H "Authorization: Bearer $CRIER_API_KEY"await fetch('https://api.usecrier.com/v1/webhook-endpoint', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});import os, requests
requests.delete(
"https://api.usecrier.com/v1/webhook-endpoint",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)Api keys
Manage API keys. Only from the dashboard, so a leaked key cannot mint new ones.
/v1/api-keysList API keys
Dashboard onlyResponse 200
data []
idstringrequirednamestringrequiredprefixstringrequiredcreatedAtstring (date-time)requiredrevokedAtstring (date-time)optional
curl "https://api.usecrier.com/v1/api-keys" \
-H "Authorization: Bearer $CRIER_API_KEY"const res = await fetch('https://api.usecrier.com/v1/api-keys', {
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.usecrier.com/v1/api-keys",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)
data = res.json()["data"]/v1/api-keysCreate an API key
Dashboard onlyBody
namestringrequired
Response 201
data
keyobjectrequiredkey
idstringrequirednamestringrequiredprefixstringrequiredcreatedAtstring (date-time)requiredrevokedAtstring (date-time)optional
secretstringrequiredThe full key, shown only this once.
curl -X POST "https://api.usecrier.com/v1/api-keys" \
-H "Authorization: Bearer $CRIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "production"
}'const res = await fetch('https://api.usecrier.com/v1/api-keys', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "production"
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://api.usecrier.com/v1/api-keys",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
json={
"name": "production"
},
)
data = res.json()["data"]/v1/api-keys/{id}Revoke an API key
Dashboard onlyParameters
idstringrequired
Response 204
No content
curl -X DELETE "https://api.usecrier.com/v1/api-keys/key_2b4n6m" \
-H "Authorization: Bearer $CRIER_API_KEY"await fetch('https://api.usecrier.com/v1/api-keys/key_2b4n6m', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CRIER_API_KEY}`,
},
});import os, requests
requests.delete(
"https://api.usecrier.com/v1/api-keys/key_2b4n6m",
headers={"Authorization": f"Bearer {os.environ['CRIER_API_KEY']}"},
)