BuddyPad API

Reference

Every call goes to https://api.buddypad.builtbymo.dev/v1 with Authorization: Bearer bp_.... It takes JSON and answers JSON. The examples below are real answers from a test account.

CallPermission
GET/v1/meread
GET/v1/pairsread
GET/v1/pairs/{pair_id}read
POST/v1/pairs/{pair_id}/nudgesbuddy
GET/v1/itemsread
POST/v1/itemsgoals
GET/v1/items/{item_id}read
PATCH/v1/items/{item_id}goals
DELETE/v1/items/{item_id}goals
POST/v1/items/{item_id}/completegoals
POST/v1/items/{item_id}/sharegoals
DELETE/v1/items/{item_id}/share/{pair_id}goals
POST/v1/items/{item_id}/copygoals
POST/v1/items/{item_id}/movegoals
GET/v1/items/{item_id}/commentsread
POST/v1/items/{item_id}/commentsbuddy
PUT/v1/items/{item_id}/reactionbuddy
POST/v1/items/{item_id}/checkinsbuddy
POST/v1/items/{item_id}/suggestionsbuddy
GET/v1/nudgesread
GET/v1/checkinsread
POST/v1/checkins/{checkin_id}/responsebuddy
GET/v1/suggestionsread
POST/v1/suggestions/{suggestion_id}/acceptgoals
POST/v1/suggestions/{suggestion_id}/declinegoals
GET/v1/eventsread
GET/v1/webhookswebhooks
POST/v1/webhookswebhooks
DELETE/v1/webhooks/{webhook_id}webhooks
POST/v1/webhooks/{webhook_id}/rotate-secretwebhooks
POST/v1/webhooks/{webhook_id}/testwebhooks
POST/v1/webhooks/{webhook_id}/resumewebhooks
GET/v1/webhooks/{webhook_id}/deliverieswebhooks

Error codes

Every error has the same shape. See Errors.

unauthorized forbidden_scope not_found conflict invalid rate_limited cursor_expired internal

Event types

item.created item.updated item.completed item.deleted item.shared item.unshared comment.created reaction.set nudge.received checkin.received checkin.answered suggestion.received suggestion.accepted suggestion.declined pair.started pair.ended

Profile

GET/v1/me

Your profile

Permission: read

Example

curl https://api.buddypad.builtbymo.dev/v1/me \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN"

Answers 200:

{
  "id": "00000000-0000-4000-8000-00000000a001",
  "display_name": "Ana",
  "avatar_path": null
}

Responses

200Your profile
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

Pairs

GET/v1/pairs

Your active buddy pairs, each with the buddy's name and the pair's streak

Permission: read

Parameters

NameIn
limitqueryoptional
cursorqueryoptional. A next_cursor from an earlier page.

Example

curl https://api.buddypad.builtbymo.dev/v1/pairs \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN"

Answers 200:

{
  "data": [
    {
      "id": "6d8afa93-4409-4e49-a788-76e4a84a75f5",
      "week_start": 1,
      "created_at": "2026-11-02T07:42:58.347663+00:00",
      "buddy": {
        "id": "00000000-0000-4000-8000-00000000a002",
        "display_name": "Ben",
        "avatar_path": null
      },
      "streak": 1,
      "current_week": "2026-11-02"
    },
    {
      "id": "e6317f9e-5358-4c3d-8352-80fc7f6cb815",
      "week_start": 1,
      "created_at": "2026-11-02T07:42:58.347663+00:00",
      "buddy": {
        "id": "00000000-0000-4000-8000-00000000a003",
        "display_name": "Cy",
        "avatar_path": null
      },
      "streak": 0,
      "current_week": "2026-11-02"
    }
  ],
  "next_cursor": null
}

Responses

200A page of pairs
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

GET/v1/pairs/{pair_id}

One active pair

Permission: read

Parameters

NameIn
pair_idpathrequired

Example

curl https://api.buddypad.builtbymo.dev/v1/pairs/6d8afa93-4409-4e49-a788-76e4a84a75f5 \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN"

Answers 200:

{
  "id": "6d8afa93-4409-4e49-a788-76e4a84a75f5",
  "week_start": 1,
  "created_at": "2026-11-02T07:42:58.347663+00:00",
  "buddy": {
    "id": "00000000-0000-4000-8000-00000000a002",
    "display_name": "Ben",
    "avatar_path": null
  },
  "streak": 1,
  "current_week": "2026-11-02"
}

Responses

200The pair
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

Goals

GET/v1/items

Goals you can see (yours, and your buddies' goals shared into a pair you are in)

Permission: read

Parameters

NameIn
pair_idqueryoptional. Only goals shared into this pair.
ownerqueryoptional. Only your goals (me) or only your buddies' (buddy).
limitqueryoptional
cursorqueryoptional. A next_cursor from an earlier page.

Example

curl "https://api.buddypad.builtbymo.dev/v1/items?pair_id=6d8afa93-4409-4e49-a788-76e4a84a75f5" \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN"

Answers 200:

{
  "data": [
    {
      "id": "a37d1e68-06e6-4a5f-bbcf-2080b74f201f",
      "owner_id": "00000000-0000-4000-8000-00000000a002",
      "title": "Send 10 applications",
      "content": [],
      "status": "todo",
      "blocked_reason": null,
      "due_at": null,
      "recurrence": null,
      "progress": null,
      "created_at": "2026-11-02T07:42:58.347663+00:00",
      "updated_at": "2026-11-02T07:42:58.347663+00:00",
      "deleted_at": null
    },
    {
      "id": "d62e1332-8734-4daf-b7b8-01c942af9821",
      "owner_id": "00000000-0000-4000-8000-00000000a001",
      "title": "Run 3x",
      "content": [],
      "status": "todo",
      "blocked_reason": null,
      "due_at": null,
      "recurrence": null,
      "progress": null,
      "created_at": "2026-11-02T07:42:58.347663+00:00",
      "updated_at": "2026-11-02T07:42:58.347663+00:00",
      "deleted_at": null
    }
  ],
  "next_cursor": null
}

Responses

200A page of goals
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

POST/v1/items

Add a goal, optionally shared into a pair

Send your own id, or one is derived from the Idempotency-Key, so a retry creates the goal once. A replay returns the goal as it is now, with the header Idempotent-Replayed. The status cannot be done: complete it.

Permission: goals

Parameters

NameIn
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Body

FieldType
idstring (uuid)optional
pair_idstring (uuid)optional
titlestringrequired
contentarray of objectoptional
statusstringoptional
blocked_reasonstring or nulloptional
due_atstring or null (date-time)optional
recurrenceobject or nulloptional
progressobject or nulloptional

Example

curl -X POST https://api.buddypad.builtbymo.dev/v1/items \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"title":"Read 20 pages","pair_id":"6d8afa93-4409-4e49-a788-76e4a84a75f5"}'

Answers 201:

{
  "id": "f62cf6ea-b23b-5355-b541-5a1cf28420b1",
  "owner_id": "00000000-0000-4000-8000-00000000a001",
  "title": "Read 20 pages",
  "content": [],
  "status": "todo",
  "blocked_reason": null,
  "due_at": null,
  "recurrence": null,
  "progress": null,
  "created_at": "2026-11-02T07:43:00.408067+00:00",
  "updated_at": "2026-11-02T07:43:00.408067+00:00",
  "deleted_at": null
}

Responses

201The goal
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

GET/v1/items/{item_id}

One goal

Permission: read

Parameters

NameIn
item_idpathrequired

Example

curl https://api.buddypad.builtbymo.dev/v1/items/d62e1332-8734-4daf-b7b8-01c942af9821 \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN"

Answers 200:

{
  "id": "d62e1332-8734-4daf-b7b8-01c942af9821",
  "owner_id": "00000000-0000-4000-8000-00000000a001",
  "title": "Run 3x",
  "content": [],
  "status": "todo",
  "blocked_reason": null,
  "due_at": null,
  "recurrence": null,
  "progress": null,
  "created_at": "2026-11-02T07:42:58.347663+00:00",
  "updated_at": "2026-11-02T07:42:58.347663+00:00",
  "deleted_at": null
}

Responses

200The goal
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

PATCH/v1/items/{item_id}

Change your own goal

Changes only the fields you send. status may be todo, doing or blocked; completing is POST /items/{item_id}/complete. blocked_reason must be null unless the status is blocked, so send "blocked_reason": null when you leave blocked.

Permission: goals

Parameters

NameIn
item_idpathrequired
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Body

FieldType
titlestringoptional
contentarray of objectoptional
statusstringoptional
blocked_reasonstring or nulloptional
due_atstring or null (date-time)optional
recurrenceobject or nulloptional
progressobject or nulloptional

Example

curl -X PATCH https://api.buddypad.builtbymo.dev/v1/items/6f5aafd7-47ae-573f-85de-39af31cebd5a \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"title":"Renamed"}'

Answers 200:

{
  "id": "6f5aafd7-47ae-573f-85de-39af31cebd5a",
  "owner_id": "00000000-0000-4000-8000-00000000a001",
  "title": "Renamed",
  "content": [],
  "status": "todo",
  "blocked_reason": null,
  "due_at": null,
  "recurrence": null,
  "progress": null,
  "created_at": "2026-11-02T07:43:00.486441+00:00",
  "updated_at": "2026-11-02T07:43:00.504809+00:00",
  "deleted_at": null
}

Responses

200The goal
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

DELETE/v1/items/{item_id}

Delete your own goal

Permission: goals

Parameters

NameIn
item_idpathrequired
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Example

curl -X DELETE https://api.buddypad.builtbymo.dev/v1/items/c47747ae-f55d-59fd-9683-bfd135e36a33 \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"

Answers 204 with no body.

Responses

204Deleted
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

POST/v1/items/{item_id}/complete

Complete your own goal (a recurring goal rolls forward to its next date)

Permission: goals

Parameters

NameIn
item_idpathrequired
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Example

curl -X POST https://api.buddypad.builtbymo.dev/v1/items/8453da75-ff76-503b-a8cb-7058ae16b55d/complete \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"

Answers 200:

{
  "id": "8453da75-ff76-503b-a8cb-7058ae16b55d",
  "owner_id": "00000000-0000-4000-8000-00000000a001",
  "title": "Contract goal",
  "content": [],
  "status": "done",
  "blocked_reason": null,
  "due_at": null,
  "recurrence": null,
  "progress": null,
  "created_at": "2026-11-02T07:43:00.58146+00:00",
  "updated_at": "2026-11-02T07:43:00.59861+00:00",
  "deleted_at": null
}

Responses

200The goal after completing
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

POST/v1/items/{item_id}/share

Share your own goal into a pair

Permission: goals

Parameters

NameIn
item_idpathrequired
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Body

FieldType
pair_idstring (uuid)required

Example

curl -X POST https://api.buddypad.builtbymo.dev/v1/items/9c2d75df-d29a-5c96-88f9-0b32fc39c660/share \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"pair_id":"e6317f9e-5358-4c3d-8352-80fc7f6cb815"}'

Answers 200:

{
  "id": "9c2d75df-d29a-5c96-88f9-0b32fc39c660",
  "owner_id": "00000000-0000-4000-8000-00000000a001",
  "title": "Contract goal",
  "content": [],
  "status": "todo",
  "blocked_reason": null,
  "due_at": null,
  "recurrence": null,
  "progress": null,
  "created_at": "2026-11-02T07:43:00.620191+00:00",
  "updated_at": "2026-11-02T07:43:00.620191+00:00",
  "deleted_at": null
}

Responses

200The goal
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

DELETE/v1/items/{item_id}/share/{pair_id}

Stop sharing your own goal into a pair

Permission: goals

Parameters

NameIn
item_idpathrequired
pair_idpathrequired
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Example

curl -X DELETE https://api.buddypad.builtbymo.dev/v1/items/1627cd14-8fb0-52e8-b264-2f49caf66f0b/share/6d8afa93-4409-4e49-a788-76e4a84a75f5 \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"

Answers 200:

{
  "id": "1627cd14-8fb0-52e8-b264-2f49caf66f0b",
  "owner_id": "00000000-0000-4000-8000-00000000a001",
  "title": "Contract goal",
  "content": [],
  "status": "todo",
  "blocked_reason": null,
  "due_at": null,
  "recurrence": null,
  "progress": null,
  "created_at": "2026-11-02T07:43:00.647088+00:00",
  "updated_at": "2026-11-02T07:43:00.647088+00:00",
  "deleted_at": null
}

Responses

200The goal
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

POST/v1/items/{item_id}/copy

Copy your own goal into a pair as a new goal

Permission: goals

Parameters

NameIn
item_idpathrequired
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Body

FieldType
pair_idstring (uuid)required
new_idstring (uuid)optional

Example

curl -X POST https://api.buddypad.builtbymo.dev/v1/items/73b2bf69-d68c-5c0d-96f9-fb1368c55490/copy \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"pair_id":"e6317f9e-5358-4c3d-8352-80fc7f6cb815"}'

Answers 201:

{
  "id": "2ce181fd-6931-5e44-aca8-3ee4b8bebeb8",
  "owner_id": "00000000-0000-4000-8000-00000000a001",
  "title": "Contract goal",
  "content": [],
  "status": "todo",
  "blocked_reason": null,
  "due_at": null,
  "recurrence": null,
  "progress": null,
  "created_at": "2026-11-02T07:43:00.712169+00:00",
  "updated_at": "2026-11-02T07:43:00.712169+00:00",
  "deleted_at": null
}

Responses

201The new goal
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

POST/v1/items/{item_id}/move

Move your own goal from one pair to another

Permission: goals

Parameters

NameIn
item_idpathrequired
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Body

FieldType
from_pair_idstring (uuid)required
to_pair_idstring (uuid)required

Example

curl -X POST https://api.buddypad.builtbymo.dev/v1/items/9518aeb5-fd72-577d-9299-61377932e713/move \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"from_pair_id":"6d8afa93-4409-4e49-a788-76e4a84a75f5","to_pair_id":"e6317f9e-5358-4c3d-8352-80fc7f6cb815"}'

Answers 200:

{
  "id": "9518aeb5-fd72-577d-9299-61377932e713",
  "owner_id": "00000000-0000-4000-8000-00000000a001",
  "title": "Contract goal",
  "content": [],
  "status": "todo",
  "blocked_reason": null,
  "due_at": null,
  "recurrence": null,
  "progress": null,
  "created_at": "2026-11-02T07:43:00.728515+00:00",
  "updated_at": "2026-11-02T07:43:00.728515+00:00",
  "deleted_at": null
}

Responses

200The goal
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

POST/v1/suggestions/{suggestion_id}/accept

Accept a suggestion on your own goal (the goal changes)

Permission: goals

Parameters

NameIn
suggestion_idpathrequired
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Example

curl -X POST https://api.buddypad.builtbymo.dev/v1/suggestions/00000000-0000-4000-8000-0000000c5001/accept \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"

Answers 200:

{
  "id": "d62e1332-8734-4daf-b7b8-01c942af9821",
  "owner_id": "00000000-0000-4000-8000-00000000a001",
  "title": "Run 4x",
  "content": [],
  "status": "todo",
  "blocked_reason": null,
  "due_at": null,
  "recurrence": null,
  "progress": null,
  "created_at": "2026-11-02T07:42:58.347663+00:00",
  "updated_at": "2026-11-02T07:43:00.95491+00:00",
  "deleted_at": null
}

Responses

200The goal after the change
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

POST/v1/suggestions/{suggestion_id}/decline

Decline a suggestion on your own goal

Permission: goals

Parameters

NameIn
suggestion_idpathrequired
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Example

curl -X POST https://api.buddypad.builtbymo.dev/v1/suggestions/00000000-0000-4000-8000-0000000c5002/decline \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"

Answers 200:

{
  "id": "00000000-0000-4000-8000-0000000c5002",
  "pair_id": "6d8afa93-4409-4e49-a788-76e4a84a75f5",
  "item_id": "d62e1332-8734-4daf-b7b8-01c942af9821",
  "suggester_id": "00000000-0000-4000-8000-00000000a002",
  "patch": {
    "title": "Run 5x"
  },
  "status": "declined",
  "created_at": "2026-11-02T07:42:58.347663+00:00",
  "decided_at": "2026-11-02T07:43:00.967893+00:00",
  "updated_at": "2026-11-02T07:43:00.972025+00:00"
}

Responses

200The suggestion
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

Buddy

POST/v1/pairs/{pair_id}/nudges

Nudge your buddy about one of their shared goals (the goal owner's nudge limit applies)

The Idempotency-Key is the nudge's id. A retry with the same key returns the same nudge.

Permission: buddy

Parameters

NameIn
pair_idpathrequired
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Body

FieldType
item_idstring (uuid)required
messagestringrequired

Example

curl -X POST https://api.buddypad.builtbymo.dev/v1/pairs/6d8afa93-4409-4e49-a788-76e4a84a75f5/nudges \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"item_id":"a37d1e68-06e6-4a5f-bbcf-2080b74f201f","message":"You got this"}'

Answers 201:

{
  "id": "6c4b5550-81e8-4383-bff9-9bf07e82452b",
  "pair_id": "6d8afa93-4409-4e49-a788-76e4a84a75f5",
  "item_id": "a37d1e68-06e6-4a5f-bbcf-2080b74f201f",
  "sender_id": "00000000-0000-4000-8000-00000000a001",
  "message": "You got this",
  "created_at": "2026-11-02T07:43:00.306859+00:00"
}

Responses

201The nudge
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

GET/v1/items/{item_id}/comments

Comments on a goal you can see

Permission: read

Parameters

NameIn
item_idpathrequired
pair_idqueryoptional. Only comments in this pair.
limitqueryoptional
cursorqueryoptional. A next_cursor from an earlier page.

Example

curl https://api.buddypad.builtbymo.dev/v1/items/d62e1332-8734-4daf-b7b8-01c942af9821/comments \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN"

Answers 200:

{
  "data": [
    {
      "id": "0472b810-5c12-4c60-b162-c897bf4a0cf5",
      "pair_id": "6d8afa93-4409-4e49-a788-76e4a84a75f5",
      "item_id": "d62e1332-8734-4daf-b7b8-01c942af9821",
      "author_id": "00000000-0000-4000-8000-00000000a002",
      "kind": "comment",
      "body": "Nice start",
      "created_at": "2026-11-02T07:42:58.347663+00:00"
    }
  ],
  "next_cursor": null
}

Responses

200A page of comments
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

POST/v1/items/{item_id}/comments

Comment on a goal shared into a pair you are in (offer_help is for the buddy, never the owner)

Permission: buddy

Parameters

NameIn
item_idpathrequired
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Body

FieldType
idstring (uuid)optional
pair_idstring (uuid)required
bodystringrequired
kindstringoptional

Example

curl -X POST https://api.buddypad.builtbymo.dev/v1/items/a37d1e68-06e6-4a5f-bbcf-2080b74f201f/comments \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"pair_id":"6d8afa93-4409-4e49-a788-76e4a84a75f5","body":"Nice"}'

Answers 201:

{
  "id": "7382b345-eb66-53a1-b479-08d617689c6a",
  "pair_id": "6d8afa93-4409-4e49-a788-76e4a84a75f5",
  "item_id": "a37d1e68-06e6-4a5f-bbcf-2080b74f201f",
  "author_id": "00000000-0000-4000-8000-00000000a001",
  "kind": "comment",
  "body": "Nice",
  "created_at": "2026-11-02T07:43:00.781168+00:00"
}

Responses

201The comment
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

PUT/v1/items/{item_id}/reaction

Set or clear your reaction on a goal shared into a pair you are in

Permission: buddy

Parameters

NameIn
item_idpathrequired
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Body

FieldType
pair_idstring (uuid)required
emojistringrequired
activebooleanrequired

Example

curl -X PUT https://api.buddypad.builtbymo.dev/v1/items/a37d1e68-06e6-4a5f-bbcf-2080b74f201f/reaction \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"pair_id":"6d8afa93-4409-4e49-a788-76e4a84a75f5","emoji":"🔥","active":true}'

Answers 200:

{
  "pair_id": "6d8afa93-4409-4e49-a788-76e4a84a75f5",
  "item_id": "a37d1e68-06e6-4a5f-bbcf-2080b74f201f",
  "user_id": "00000000-0000-4000-8000-00000000a001",
  "emoji": "🔥",
  "active": true,
  "updated_at": "2026-11-02T07:43:00.815037+00:00"
}

Responses

200The reaction
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

POST/v1/items/{item_id}/checkins

Ask your buddy how a shared goal is going (one open check-in per goal per pair)

Permission: buddy

Parameters

NameIn
item_idpathrequired
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Body

FieldType
idstring (uuid)optional
pair_idstring (uuid)required

Example

curl -X POST https://api.buddypad.builtbymo.dev/v1/items/a37d1e68-06e6-4a5f-bbcf-2080b74f201f/checkins \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"pair_id":"6d8afa93-4409-4e49-a788-76e4a84a75f5"}'

Answers 201:

{
  "id": "7f890d6b-d5e6-57bd-8204-49e4219bdafd",
  "pair_id": "6d8afa93-4409-4e49-a788-76e4a84a75f5",
  "item_id": "a37d1e68-06e6-4a5f-bbcf-2080b74f201f",
  "asker_id": "00000000-0000-4000-8000-00000000a001",
  "asked_at": "2026-11-02T07:43:00.826134+00:00",
  "response": null,
  "note": null,
  "responded_at": null,
  "updated_at": "2026-11-02T07:43:00.826134+00:00"
}

Responses

201The check-in
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

POST/v1/items/{item_id}/suggestions

Suggest an edit to your buddy's shared goal (a new title, a new due date, or both)

Permission: buddy

Parameters

NameIn
item_idpathrequired
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Body

FieldType
idstring (uuid)optional
pair_idstring (uuid)required
patchobjectrequired

Example

curl -X POST https://api.buddypad.builtbymo.dev/v1/items/a37d1e68-06e6-4a5f-bbcf-2080b74f201f/suggestions \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"pair_id":"6d8afa93-4409-4e49-a788-76e4a84a75f5","patch":{"title":"Send 12 applications"}}'

Answers 201:

{
  "id": "29f861dd-80ff-58a9-8e5f-838f291fb57b",
  "pair_id": "6d8afa93-4409-4e49-a788-76e4a84a75f5",
  "item_id": "a37d1e68-06e6-4a5f-bbcf-2080b74f201f",
  "suggester_id": "00000000-0000-4000-8000-00000000a001",
  "patch": {
    "title": "Send 12 applications"
  },
  "status": "pending",
  "created_at": "2026-11-02T07:43:00.85656+00:00",
  "decided_at": null,
  "updated_at": "2026-11-02T07:43:00.85656+00:00"
}

Responses

201The suggestion
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

GET/v1/nudges

Nudges on goals shared into your pairs, sent by you or to you

Permission: read

Parameters

NameIn
pair_idqueryoptional
item_idqueryoptional
limitqueryoptional
cursorqueryoptional. A next_cursor from an earlier page.

Example

curl https://api.buddypad.builtbymo.dev/v1/nudges \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN"

Answers 200:

{
  "data": [
    {
      "id": "08438569-a440-400a-b8bb-51ec0d53a78b",
      "pair_id": "6d8afa93-4409-4e49-a788-76e4a84a75f5",
      "item_id": "d62e1332-8734-4daf-b7b8-01c942af9821",
      "sender_id": "00000000-0000-4000-8000-00000000a002",
      "message": "Go Ana",
      "created_at": "2026-11-02T07:42:58.347663+00:00"
    },
    {
      "id": "6c4b5550-81e8-4383-bff9-9bf07e82452b",
      "pair_id": "6d8afa93-4409-4e49-a788-76e4a84a75f5",
      "item_id": "a37d1e68-06e6-4a5f-bbcf-2080b74f201f",
      "sender_id": "00000000-0000-4000-8000-00000000a001",
      "message": "You got this",
      "created_at": "2026-11-02T07:43:00.306859+00:00"
    }
  ],
  "next_cursor": null
}

Responses

200A page of nudges
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

GET/v1/checkins

Check-ins on goals shared into your pairs

Permission: read

Parameters

NameIn
pair_idqueryoptional
item_idqueryoptional
limitqueryoptional
cursorqueryoptional. A next_cursor from an earlier page.

Example

curl "https://api.buddypad.builtbymo.dev/v1/checkins?item_id=d62e1332-8734-4daf-b7b8-01c942af9821" \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN"

Answers 200:

{
  "data": [
    {
      "id": "00000000-0000-4000-8000-0000000c0001",
      "pair_id": "6d8afa93-4409-4e49-a788-76e4a84a75f5",
      "item_id": "d62e1332-8734-4daf-b7b8-01c942af9821",
      "asker_id": "00000000-0000-4000-8000-00000000a002",
      "asked_at": "2026-11-02T07:42:58.347663+00:00",
      "response": null,
      "note": null,
      "responded_at": null,
      "updated_at": "2026-11-02T07:42:58.347663+00:00"
    }
  ],
  "next_cursor": null
}

Responses

200A page of check-ins
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

POST/v1/checkins/{checkin_id}/response

Answer a check-in on your own goal

Permission: buddy

Parameters

NameIn
checkin_idpathrequired
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Body

FieldType
responsestringrequired
notestring or nulloptional

Example

curl -X POST https://api.buddypad.builtbymo.dev/v1/checkins/00000000-0000-4000-8000-0000000c0001/response \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"response":"on_track","note":"Twice so far"}'

Answers 200:

{
  "id": "00000000-0000-4000-8000-0000000c0001",
  "pair_id": "6d8afa93-4409-4e49-a788-76e4a84a75f5",
  "item_id": "d62e1332-8734-4daf-b7b8-01c942af9821",
  "asker_id": "00000000-0000-4000-8000-00000000a002",
  "asked_at": "2026-11-02T07:42:58.347663+00:00",
  "response": "on_track",
  "note": "Twice so far",
  "responded_at": "2026-11-02T07:43:00.916697+00:00",
  "updated_at": "2026-11-02T07:43:00.921277+00:00"
}

Responses

200The check-in
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

GET/v1/suggestions

Edit suggestions on goals shared into your pairs

Permission: read

Parameters

NameIn
pair_idqueryoptional
item_idqueryoptional
limitqueryoptional
cursorqueryoptional. A next_cursor from an earlier page.

Example

curl https://api.buddypad.builtbymo.dev/v1/suggestions \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN"

Answers 200:

{
  "data": [
    {
      "id": "00000000-0000-4000-8000-0000000c5001",
      "pair_id": "6d8afa93-4409-4e49-a788-76e4a84a75f5",
      "item_id": "d62e1332-8734-4daf-b7b8-01c942af9821",
      "suggester_id": "00000000-0000-4000-8000-00000000a002",
      "patch": {
        "title": "Run 4x"
      },
      "status": "pending",
      "created_at": "2026-11-02T07:42:58.347663+00:00",
      "decided_at": null,
      "updated_at": "2026-11-02T07:42:58.347663+00:00"
    },
    {
      "id": "00000000-0000-4000-8000-0000000c5002",
      "pair_id": "6d8afa93-4409-4e49-a788-76e4a84a75f5",
      "item_id": "d62e1332-8734-4daf-b7b8-01c942af9821",
      "suggester_id": "00000000-0000-4000-8000-00000000a002",
      "patch": {
        "title": "Run 5x"
      },
      "status": "pending",
      "created_at": "2026-11-02T07:42:58.347663+00:00",
      "decided_at": null,
      "updated_at": "2026-11-02T07:42:58.347663+00:00"
    }
  ],
  "next_cursor": null
}

Responses

200A page of suggestions
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

Events

GET/v1/events

What changed, in order, exactly once

Thin events (a type, ids, the actor and a time; never a copy of the object). Fetch the object to see it: you get it only if you can still see it. Keep next_cursor and pass it as after. Omit after to start from the oldest event you still have; pass after=head to start from now. Events are kept 30 days. When events after your cursor have aged out you get 410 cursor_expired: re-read the current state, then continue from after=head.

Permission: read

Parameters

NameIn
afterqueryoptional. A next_cursor from an earlier page, or head.
limitqueryoptional

Example

curl https://api.buddypad.builtbymo.dev/v1/events \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN"

Answers 200:

{
  "data": [
    {
      "id": "1",
      "type": "pair.started",
      "actor_id": "00000000-0000-4000-8000-00000000a002",
      "object_type": "pair",
      "object_id": "6d8afa93-4409-4e49-a788-76e4a84a75f5",
      "pair_id": "6d8afa93-4409-4e49-a788-76e4a84a75f5",
      "occurred_at": "2026-11-02T07:42:58.347663+00:00"
    },
    {
      "id": "3",
      "type": "pair.started",
      "actor_id": "00000000-0000-4000-8000-00000000a003",
      "object_type": "pair",
      "object_id": "e6317f9e-5358-4c3d-8352-80fc7f6cb815",
      "pair_id": "e6317f9e-5358-4c3d-8352-80fc7f6cb815",
      "occurred_at": "2026-11-02T07:42:58.347663+00:00"
    }
  ],
  "next_cursor": "e1.WyIxNTQyIiwiNzQiXQ"
}

Responses

200A page of events
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
410Events after this cursor were deleted (code cursor_expired).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

Webhooks

GET/v1/webhooks

Your webhooks. A secret is never listed.

Permission: webhooks

Parameters

NameIn
limitqueryoptional
cursorqueryoptional. A next_cursor from an earlier page.

Example

curl https://api.buddypad.builtbymo.dev/v1/webhooks \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN"

Answers 200:

{
  "data": [
    {
      "id": "909aec92-ab10-5af8-96c4-89975f6641db",
      "url": "https://example.com/buddypad",
      "event_types": [
        "item.completed"
      ],
      "active": true,
      "paused_reason": null,
      "failing_since": null,
      "last_delivered_at": null,
      "previous_secret_expires_at": null,
      "created_at": "2026-11-02T07:43:01.01442+00:00",
      "updated_at": "2026-11-02T07:43:01.01442+00:00"
    }
  ],
  "next_cursor": null
}

Responses

200A page of webhooks
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

POST/v1/webhooks

Register a webhook. The signing secret comes back once, in this response.

The url must be https and must point at a public address. At most 10 webhooks per person. Only events that happen after this call are delivered; read GET /events for anything earlier. A retry with the same Idempotency-Key answers with the same webhook and "secret": null, because a secret is shown once. If that response was lost, call rotate-secret.

Permission: webhooks

Parameters

NameIn
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Body

FieldType
idstring (uuid)optional
urlstringrequired. https, and a public address. No redirects are followed.
event_typesarray of stringrequired. The event types to send (see Event).

Example

curl -X POST https://api.buddypad.builtbymo.dev/v1/webhooks \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/buddypad","event_types":["item.completed","nudge.received"]}'

Answers 201:

{
  "id": "c44090e3-648d-53eb-a7ed-af825c0a14e3",
  "url": "https://example.com/buddypad",
  "active": true,
  "secret": "whsec_0123456789abcdefghijklmnopqrstuvwxyzABCDEFG",
  "created_at": "2026-11-02T07:43:01.052089+00:00",
  "updated_at": "2026-11-02T07:43:01.052089+00:00",
  "event_types": [
    "item.completed",
    "nudge.received"
  ],
  "failing_since": null,
  "paused_reason": null,
  "last_delivered_at": null,
  "previous_secret_expires_at": null
}

Responses

201The webhook and its secret
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

DELETE/v1/webhooks/{webhook_id}

Delete a webhook and its secrets

Permission: webhooks

Parameters

NameIn
webhook_idpathrequired
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Example

curl -X DELETE https://api.buddypad.builtbymo.dev/v1/webhooks/dcfa8529-8822-5cb0-9bcd-3021d7fc7eed \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"

Answers 204 with no body.

Responses

204Deleted
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

POST/v1/webhooks/{webhook_id}/rotate-secret

Get a new signing secret. The old one keeps working for 24 hours.

For those 24 hours each delivery carries two v1 signatures, so a receiver on either secret verifies. A retry with the same Idempotency-Key rotates nothing and answers with "secret": null.

Permission: webhooks

Parameters

NameIn
webhook_idpathrequired
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Example

curl -X POST https://api.buddypad.builtbymo.dev/v1/webhooks/f39b0cf3-3757-5e0c-a779-f853e9ad0964/rotate-secret \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"

Answers 200:

{
  "secret": "whsec_0123456789abcdefghijklmnopqrstuvwxyzABCDEFG",
  "previous_secret_expires_at": "2026-11-03T07:43:01.185163+00:00"
}

Responses

200The new secret
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

POST/v1/webhooks/{webhook_id}/test

Send a signed webhook.test event to your receiver, within about a minute

One a minute per webhook. It works on a paused webhook, moves no cursor and does not resume anything. The result shows up in the delivery log with event_type webhook.test.

Permission: webhooks

Parameters

NameIn
webhook_idpathrequired
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Example

curl -X POST https://api.buddypad.builtbymo.dev/v1/webhooks/139bdf42-9190-55a1-b68f-de8dbd86f389/test \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"

Answers 202:

{
  "queued": true
}

Responses

202Queued
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

POST/v1/webhooks/{webhook_id}/resume

Turn a paused webhook back on, from now

A webhook pauses after 3 days of failed deliveries. Resuming starts from now. Read GET /events to catch up on what happened while it was paused. Resuming an active webhook changes nothing.

Permission: webhooks

Parameters

NameIn
webhook_idpathrequired
Idempotency-Keyheaderoptional. A UUID. A retry with the same key never acts twice. Echoed in the response.

Example

curl -X POST https://api.buddypad.builtbymo.dev/v1/webhooks/d20f2263-c1e4-502d-a0a7-894845db38b5/resume \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"

Answers 200:

{
  "id": "d20f2263-c1e4-502d-a0a7-894845db38b5",
  "url": "https://example.com/buddypad",
  "active": true,
  "created_at": "2026-11-02T07:43:01.273577+00:00",
  "updated_at": "2026-11-02T07:43:01.273577+00:00",
  "event_types": [
    "item.completed"
  ],
  "failing_since": null,
  "paused_reason": null,
  "last_delivered_at": null,
  "previous_secret_expires_at": null
}

Responses

200The webhook
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
409Already exists, an app limit (nudge limit, one open check-in), or a collision to retry (code conflict).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).

GET/v1/webhooks/{webhook_id}/deliveries

The delivery log, newest first, kept 30 days

Permission: webhooks

Parameters

NameIn
webhook_idpathrequired
limitqueryoptional
cursorqueryoptional. A next_cursor from an earlier page.

Example

curl https://api.buddypad.builtbymo.dev/v1/webhooks/99c13339-a3f6-5c8e-a118-2de574bcb0bf/deliveries \
  -H "Authorization: Bearer $BUDDYPAD_TOKEN"

Answers 200:

{
  "data": [],
  "next_cursor": null
}

Responses

200A page of attempts
400The request is not valid (code invalid).
401No valid token (code unauthorized).
403The token lacks this route's permission (code forbidden_scope).
404Does not exist, or is not yours to see (the same answer; code not_found).
429Over the token's limit, or too many failed authentications from this address (code rate_limited). See Retry-After.
500Something failed on our side (code internal).
503The request ran too long (code internal).