Skip to content

Instantly share code, notes, and snippets.

@danphilibin
Last active December 2, 2024 03:52
Show Gist options
  • Save danphilibin/a29f4d76ac892c1d80803085dc2cbd92 to your computer and use it in GitHub Desktop.
Save danphilibin/a29f4d76ac892c1d80803085dc2cbd92 to your computer and use it in GitHub Desktop.
Campsite Public API & Integrations Platform

Campsite Public API & Integrations Platform

When I joined Campsite in early 2024, the product was transitioning from a specialized communication tool for designers to a general communication tool for entire organizations. While customers valued Campsite's core product, integrating with customers' existing tools and workflows is table stakes for a team communication product. Without an API, potential customers struggled to convince key decision makers to switch communication tools.

Over five months, I led the development of Campsite’s public API and integrations platform from conception to general availability. The project required balancing customer needs with thoughtful API design to ensure the API was intuitive, useful, and extensible. Today, the public API has helped position Campsite as an extensible platform, and customers have used it to create over 100 custom integrations.

Technical foundations

Campsite's tech stack consists of a Ruby on Rails backend and a React/Next.js frontend. Our tooling pipeline generates an OpenAPI schema and a TypeScript client from annoted routes & controllers, and most product API routes exist under a "/v1" namespace designed only for internal use.

We decided to create a new "/v2" namespace for the public API, giving us flexibility to design a clean interface while building on our existing infrastructure and maintaining compatibility with existing internal routes.

Zapier integration

Early in the project, we weighed shipping a REST API versus a Zapier integration. Both options had clear trade-offs:

  • REST API: More flexible and powerful for developers, but it would take longer to build and validate customer needs.
  • Zapier integration: Faster to ship and offered instant access to common workflows but limited in scope compared to a custom API.

We chose to start with Zapier. This allowed us to validate customer needs and API design assumptions quickly while gathering real-world feedback before committing to a public API. For example, we learned that customers mostly wanted to create content, which led to us prioritizing "write" endpoints over "read" endpoints later on in the project.

Furthermore, much of the work we did for the Zapier integration - including the OAuth flow and most endpoint logic - could be converted into a public API.

REST API & core primitives

After gathering initial feedback from the Zapier integration, we shifted our focus to building a proper REST API under the "/v2" namespace.

We designed the REST API to map neatly to Campsite's core primitives:

  • Most discussions happen in posts & comments with a title, a body, and threaded replies (think: Facebook posts or email threads).
  • Users can chat in 1:1 DMs or group threads (think: iMessage).
  • Long-form communication can be shared via docs (think: Google Docs).

Customers told us they wanted to pipe information into Campsite to automate tasks - like creating posts for new support requests, creating comments on posts for CI/CD alerts, or sending a chat message when a new user signs up. To address these needs, we prioritized 'write' endpoints over 'get' endpoints:

  • Create a new post: POST /v2/posts
  • Create a comment on a post: POST /v2/posts/:post_id/comments
  • Create a chat message: POST /v2/threads/:thread_id/messages

We launched these endpoints with a "beta" flag and created a private channel with early testers so we could communicate ahead of breaking changes.

Our initial documentation was a one-page shared Campsite doc. I fed our OpenAPI schema into Claude and asked it to generate the initial version as a Markdown file, with updates made manually until we eventually shipped auto-generated docs a few months later.

Webhooks

After launching the REST API endpoints, customers requested real-time notifications about new content. Specifically:

  • Knowing when someone @-mentioned their integration in a post or comment.
  • Knowing when new posts appeared in channels they cared about.

We built webhooks in stages, starting with a simple "app.mentioned" event that fired whenever someone @-mentioned an integration. This let us test our webhook delivery infrastructure with a small, predictable event type.

To deliver webhooks, I leveraged our existing background job infrastructure, which uses Sidekiq to perform tasks with automatic retries and exponential backoff. I settled on three models for our webhooks system:

  • Webhook is a URL that receives events. It has an event_names parameter that defines which events it should receive.
  • One WebhookEvent is created per Webhook for a supported event like post.created or app.mentioned. We store a static copy of the payload in each row as JSON so that each delivery is sending the same payload.
  • WebhookDelivery is a record of a delivery attempt. We use it to store timestamps and responses.

CleanShot 2024-12-01 at 22 24 30@2x

Docs and client SDKs

By the time we added webhooks we were quickly outgrowing our hand-maintained docs, so I pushed forward with auto-generating documentation and client SDKs. I was set on making these as automatic as possible, so I updated our tooling to produce an OpenAPI schema file for just the public endpoints.

  • Docs: I considered a few vendors and landed on Mintlify, which supported OpenAPI-generated docs, had a visually appealing style that matched Campsite's brand aesthetic, was reasonably priced, and had a very nice CLI that supported instantly previewing docs from localhost.
  • Client SDKs: I chose Stainless because it was the first tool I had heard about (h/t Alex Arena), promised a high level of quality & polish, had many prolific API companies as customers, and worked well on first use. We decided to pursue the project on our morning sync call, and by the afternoon I was using an alpha version via NPM in our projects.

(I mention these factors because, as someone who has worked on developer tool marketing, I think a lot about what speaks to me, a developer, when evaluating tools.)

Results and impact

The initial API platform launched in June 2024, with incremental updates over the next four months that added webhooks, GET endpoints, auto-generated docs, and a GitHub repo with code samples. Today customers have created over 100 custom integrations, and several customers who were previously blocked from adopting Campsite due to integration limitations have since become active users.

To further drive adoption and demonstrate the API's capabilities, I took the lead in developing several example integrations and actively participated in our "insiders" channel to help developers and answer questions. I also built a fast idea-to-prototype pipeline for responding to customer requests and validating ideas, and wrote about that pipeline for the company blog.

Key wins:

  • Clean, intuitive API design that supports essential workflows and maps neatly to Campsite's core primitives.
  • Resilient webhook infrastructure that handles deliveries & retries.
  • Self-serve customer experience with integrations dashboard & documentation.
  • Low maintenance overhead for documentation & client SDKs.
  • Transformed Campsite from a siloed tool into an extensible platform.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment