REST API reference

Patreon API

13 endpoints for Patreon. Each one is a POST with a JSON body, called with your API key.

Base URL
https://cotlet.dev/api/v1/patreon
Connects with
Your own Patreon creator account
Integration page
Patreon
Patreon Endpoints
Endpoint Access Description
list_tiers read Your membership tiers with name, description and benefits.
list_members read Members from your Relationship manager with tier, status and join date.
export_members read The Relationship manager CSV with your filters applied, as a download link.
list_posts read Your posts, scheduled ones first, with status, audience and publish date.
get_post read Full post: title, body, tiers with access, status and URL.
list_chats read Conversations in your Patreon Chats with the member and the last message.
create_post write Save a new post as a draft. Nothing is published.
update_post write Change the title, body or audience of a draft or scheduled post.
schedule_post write Set the date and time a draft is published.
publish_post write Publish a draft now.
send_message write Direct message to one current or former paid member, as you.
message_tier write The same direct message to the members of one or more tiers.
update_tier write Change a tier's name, description or benefits.

List tiers

read

POST https://cotlet.dev/api/v1/patreon/list_tiers

Returns every tier on your Patreon page. Use the tier_id of each item in the other endpoints. Benefits are the ones shown in the tier editor.

Parameters

No parameters.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/patreon/list_tiers \
  -H "Authorization: Bearer $COTLET_API_KEY"
Python
result = client.call("patreon", "list_tiers")
Node.js
const result = await cotlet.call('patreon', 'list_tiers');
CLI
cotlet call patreon list_tiers

Example response

{
  "tiers": [
    {
      "tier_id": "24019876",
      "name": "Gold",
      "description": "Everything in Supporter plus early episodes.",
      "benefits": [
        "Episodes a week before release",
        "Monthly Q&A"
      ]
    }
  ]
}

POST https://cotlet.dev/api/v1/patreon/list_members

Lists members the way the Relationship manager does. Filter by paid or free, active or canceled, tier or join date. Pass next_cursor back as cursor for the next page.

Parameters

Parameters: list_members
NameTypeDescription
paid enum paid, free or all. Default: all.
status enum active, canceled or all. Default: active.
tier_id string Only members of this tier.
joined_since date Only members who joined on or after this date.
limit integer 1 to 100. Default: 50.
cursor string Next page cursor from the previous call.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/patreon/list_members \
  -H "Authorization: Bearer $COTLET_API_KEY"
Python
result = client.call("patreon", "list_members")
Node.js
const result = await cotlet.call('patreon', 'list_members');
CLI
cotlet call patreon list_members

Example response

{
  "members": [
    {
      "member_id": "m_4471920",
      "name": "Maya Fischer",
      "tier": "Gold",
      "status": "active",
      "paid": true,
      "joined_at": "2026-10-08T10:12:00Z"
    }
  ],
  "next_cursor": "eyJvZmZzZXQiOjUwfQ"
}

POST https://cotlet.dev/api/v1/patreon/export_members

Runs the same CSV export as the button in the Relationship manager, with the filters you pass. The file has the columns you chose in the table settings, plus Charge frequency if you offer annual memberships. It reaches no one and changes nothing.

Parameters

Parameters: export_members
NameTypeDescription
paid enum paid, free or all. Default: all.
status enum active, canceled or all. Default: active.
tier_id string Only members of this tier.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/patreon/export_members \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"paid":"paid","status":"active"}'
Python
result = client.call("patreon", "export_members", {"paid":"paid","status":"active"})
Node.js
const result = await cotlet.call('patreon', 'export_members', {"paid":"paid","status":"active"});
CLI
cotlet call patreon export_members --data '{"paid":"paid","status":"active"}'

Example response

{
  "file_url": "https://cotlet.dev/api/v1/files/exports/patreon-members-2026-10-11.csv",
  "rows": 214,
  "filters": {
    "status": "active",
    "tier_id": "24019876"
  }
}

List posts

read

POST https://cotlet.dev/api/v1/patreon/list_posts

Lists your posts. Scheduled posts come first, labeled with their date, as in the Patreon post list. Body is a short preview; get_post returns the full text.

Parameters

Parameters: list_posts
NameTypeDescription
status enum published, draft, scheduled or all. Default: all.
limit integer 1 to 50. Default: 20.
cursor string Next page cursor from the previous call.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/patreon/list_posts \
  -H "Authorization: Bearer $COTLET_API_KEY"
Python
result = client.call("patreon", "list_posts")
Node.js
const result = await cotlet.call('patreon', 'list_posts');
CLI
cotlet call patreon list_posts

Example response

{
  "posts": [
    {
      "post_id": "118204553",
      "title": "Episode 12: the full cut",
      "status": "scheduled",
      "publish_at": "2026-10-16T18:00:00+01:00",
      "audience": "paid_tiers",
      "preview": "This week we go behind the scenes..."
    }
  ],
  "next_cursor": null
}

Get post

read

POST https://cotlet.dev/api/v1/patreon/get_post

Returns one post with its full body and the tiers that can see it. Use it before update_post to see what is there now.

Parameters

Parameters: get_post
NameTypeDescription
post_id required string Post ID from list_posts.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/patreon/get_post \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"post_id":"post_8c41d2"}'
Python
result = client.call("patreon", "get_post", {"post_id":"post_8c41d2"})
Node.js
const result = await cotlet.call('patreon', 'get_post', {"post_id":"post_8c41d2"});
CLI
cotlet call patreon get_post --data '{"post_id":"post_8c41d2"}'

Example response

{
  "post_id": "118204553",
  "title": "Episode 12: the full cut",
  "body": "This week we go behind the scenes...",
  "status": "scheduled",
  "publish_at": "2026-10-16T18:00:00+01:00",
  "tier_ids": [
    "24019876"
  ],
  "url": "https://www.patreon.com/posts/episode-12-118204553"
}

List chats

read

POST https://cotlet.dev/api/v1/patreon/list_chats

Lists your Chats, most recent first, with the member, the last message and whether you sent it. Set unanswered_only to see what needs a reply.

Parameters

Parameters: list_chats
NameTypeDescription
unanswered_only boolean Skip conversations where you sent the last message.
limit integer 1 to 50. Default: 20.
cursor string Next page cursor from the previous call.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/patreon/list_chats \
  -H "Authorization: Bearer $COTLET_API_KEY"
Python
result = client.call("patreon", "list_chats")
Node.js
const result = await cotlet.call('patreon', 'list_chats');
CLI
cotlet call patreon list_chats

Example response

{
  "chats": [
    {
      "member_id": "m_4471920",
      "name": "Maya Fischer",
      "last_message": "Where do I find the Q3 files?",
      "last_from": "member",
      "updated_at": "2026-10-10T16:02:00Z"
    }
  ],
  "next_cursor": null
}

Create post

write

POST https://cotlet.dev/api/v1/patreon/create_post

Creates a draft in your Patreon post list. Nobody sees it until publish_post or schedule_post. create_post runs without asking first: it reaches no one and a draft is removed with one call in Patreon.

Parameters

Parameters: create_post
NameTypeDescription
title required string Post title.
body required string Post text. Links and images by URL.
audience enum public, all_members or paid_tiers. Default: all_members.
tier_ids string[] Tiers with access when audience is paid_tiers.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/patreon/create_post \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"title","body":"body"}'
Python
result = client.call("patreon", "create_post", {"title":"title","body":"body"})
Node.js
const result = await cotlet.call('patreon', 'create_post', {"title":"title","body":"body"});
CLI
cotlet call patreon create_post --data '{"title":"title","body":"body"}'

Example response

{
  "post_id": "118204553",
  "status": "draft",
  "audience": "paid_tiers",
  "tier_ids": [
    "24019876"
  ],
  "title": "Episode 12: the full cut"
}

Update post

write

POST https://cotlet.dev/api/v1/patreon/update_post

Edits a post that is not published yet, as you would in the post editor. It reaches no one until the post goes out, so it runs without asking first. Published posts are not changed.

Parameters

Parameters: update_post
NameTypeDescription
post_id required string Post ID from list_posts.
fields required object Any of title, body, audience, tier_ids.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/patreon/update_post \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"post_id":"post_8c41d2","fields":"fields"}'
Python
result = client.call("patreon", "update_post", {"post_id":"post_8c41d2","fields":"fields"})
Node.js
const result = await cotlet.call('patreon', 'update_post', {"post_id":"post_8c41d2","fields":"fields"});
CLI
cotlet call patreon update_post --data '{"post_id":"post_8c41d2","fields":"fields"}'

Example response

{
  "post_id": "118204553",
  "status": "draft",
  "title": "Episode 12: the director's cut"
}

Schedule post

write Confirm

POST https://cotlet.dev/api/v1/patreon/schedule_post

Schedules a draft, which then shows at the top of your post list labeled Scheduled. Set notify_members to false to switch off the member notification for this post. By default you confirm each call; you can switch that off for this tool.

Parameters

Parameters: schedule_post
NameTypeDescription
post_id required string Post ID from list_posts.
publish_at required datetime ISO 8601 with time zone.
notify_members boolean Notify members when the post goes out. Default: true.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/patreon/schedule_post \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"post_id":"118204553","publish_at":"2026-10-16T18:00:00+01:00","notify_members":true}'
Python
result = client.call("patreon", "schedule_post", {"post_id":"118204553","publish_at":"2026-10-16T18:00:00+01:00","notify_members":True})
Node.js
const result = await cotlet.call('patreon', 'schedule_post', {"post_id":"118204553","publish_at":"2026-10-16T18:00:00+01:00","notify_members":true});
CLI
cotlet call patreon schedule_post --data '{"post_id":"118204553","publish_at":"2026-10-16T18:00:00+01:00","notify_members":true}'

Example response

{
  "post_id": "118204553",
  "status": "scheduled",
  "publish_at": "2026-10-16T18:00:00+01:00",
  "audience": "paid_tiers",
  "tier_ids": [
    "24019876"
  ],
  "url": "https://www.patreon.com/posts/episode-12-118204553"
}

Publish post

write Confirm

POST https://cotlet.dev/api/v1/patreon/publish_post

Publishes a draft immediately to its audience. Members are notified unless notify_members is false. By default you confirm each call; you can switch that off for this tool.

Parameters

Parameters: publish_post
NameTypeDescription
post_id required string Post ID from list_posts.
notify_members boolean Notify members when the post goes out. Default: true.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/patreon/publish_post \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"post_id":"post_8c41d2"}'
Python
result = client.call("patreon", "publish_post", {"post_id":"post_8c41d2"})
Node.js
const result = await cotlet.call('patreon', 'publish_post', {"post_id":"post_8c41d2"});
CLI
cotlet call patreon publish_post --data '{"post_id":"post_8c41d2"}'

Example response

{
  "post_id": "118204553",
  "status": "published",
  "url": "https://www.patreon.com/posts/episode-12-118204553"
}

Send message

write Confirm

POST https://cotlet.dev/api/v1/patreon/send_message

Sends a direct message to one member in Chats. Patreon allows direct messages only to current or former paid members, so a free member returns an error. By default you confirm each call; you can switch that off for this tool.

Parameters

Parameters: send_message
NameTypeDescription
member_id required string Member ID from list_members or list_chats.
body required string Message text.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/patreon/send_message \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"member_id":"m_4471920","body":"Hi Maya, the Q3 files are in the Q3 collection, third post from the top."}'
Python
result = client.call("patreon", "send_message", {"member_id":"m_4471920","body":"Hi Maya, the Q3 files are in the Q3 collection, third post from the top."})
Node.js
const result = await cotlet.call('patreon', 'send_message', {"member_id":"m_4471920","body":"Hi Maya, the Q3 files are in the Q3 collection, third post from the top."});
CLI
cotlet call patreon send_message --data '{"member_id":"m_4471920","body":"Hi Maya, the Q3 files are in the Q3 collection, third post from the top."}'

Example response

{
  "member_id": "m_4471920",
  "status": "sent",
  "sent_at": "2026-10-11T09:05:00+02:00"
}

Message tier

write Confirm

POST https://cotlet.dev/api/v1/patreon/message_tier

Sends one message to the members of the tiers you name, as the Relationship manager does when you filter by tier. Only paid members can be messaged. By default you confirm each call; you can switch that off for this tool.

Parameters

Parameters: message_tier
NameTypeDescription
tier_ids required string[] Tier IDs from list_tiers.
body required string Message text.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/patreon/message_tier \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tier_ids":["24019876","24019877"],"body":"Your October pack is ready: https://example.com/october-pack. Thanks for being here!"}'
Python
result = client.call("patreon", "message_tier", {"tier_ids":["24019876","24019877"],"body":"Your October pack is ready: https://example.com/october-pack. Thanks for being here!"})
Node.js
const result = await cotlet.call('patreon', 'message_tier', {"tier_ids":["24019876","24019877"],"body":"Your October pack is ready: https://example.com/october-pack. Thanks for being here!"});
CLI
cotlet call patreon message_tier --data '{"tier_ids":["24019876","24019877"],"body":"Your October pack is ready: https://example.com/october-pack. Thanks for being here!"}'

Example response

{
  "tier_ids": [
    "24019876"
  ],
  "status": "sent",
  "recipients": 214
}

Update tier

write Confirm

POST https://cotlet.dev/api/v1/patreon/update_tier

Edits the fields at the top of the tier editor: name, description and benefits. Members see the change on your page. Prices are not changed by this tool. By default you confirm each call; you can switch that off for this tool.

Parameters

Parameters: update_tier
NameTypeDescription
tier_id required string Tier ID from list_tiers.
fields required object Any of name, description, benefits (string[]).

Request

cURL
curl -X POST https://cotlet.dev/api/v1/patreon/update_tier \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tier_id":"tier_8c41d2","fields":"fields"}'
Python
result = client.call("patreon", "update_tier", {"tier_id":"tier_8c41d2","fields":"fields"})
Node.js
const result = await cotlet.call('patreon', 'update_tier', {"tier_id":"tier_8c41d2","fields":"fields"});
CLI
cotlet call patreon update_tier --data '{"tier_id":"tier_8c41d2","fields":"fields"}'

Example response

{
  "tier_id": "24019876",
  "name": "Gold",
  "benefits": [
    "Episodes a week before release",
    "Monthly Q&A",
    "Monthly Q&A call"
  ],
  "status": "updated"
}