{"id":18744,"date":"2018-11-29T16:19:30","date_gmt":"2018-11-29T16:19:30","guid":{"rendered":"https:\/\/www.intercom.com\/blog\/?p=18744"},"modified":"2020-07-30T12:55:24","modified_gmt":"2020-07-30T11:55:24","slug":"api-versioning","status":"publish","type":"post","link":"https:\/\/www.intercom.com\/blog\/api-versioning\/","title":{"rendered":"Growing a platform: Introducing API versioning in Intercom"},"content":{"rendered":"<p>We believe that <a href=\"https:\/\/www.intercom.com\/blog\/shipping-is-your-companys-heartbeat\/\" target=\"_blank\" rel=\"noopener noreferrer\">shipping is our company\u2019s heartbeat<\/a> and that we should ship frequently with small incremental changes. This principle enables us to get feedback and iterate quickly.<\/p>\n<p>However, until recently we couldn\u2019t apply the same philosophy to our APIs. We weren\u2019t able to fix bugs, improve the functionality of our APIs or even keep up with our constantly growing products. That&#8217;s because API interfaces are like contracts, which can\u2019t be easily changed once released to the world.<\/p>\n<p>Developers building on the Intercom platform rely on the current existing functionality of our APIs, and potentially backwards incompatible changes might break the flows in which they are used. Any changes generally require advance notice to developers to let them know that their app will be affected and that they should migrate to the new functionality. Forcing an update also means that developers have to allocate the needed resources to update their apps, which can be quite time consuming depending on the changes.<\/p>\n<blockquote class=\"pullquote-style-one\"><p>&#8220;API interfaces are like contracts, which can\u2019t be easily changed once released to the world&#8221;<\/p><\/blockquote>\n<p>Even with enough notice, rolling out changes that break things is not straightforward \u2013 coordinating our release with our developers as they update their apps has to happen in a way that we avoid intermediate states where the functionality is broken. If there\u2019s a problem, rolling back to the old state isn\u2019t always easy. This ends up being a no-go for us in most cases because it\u2019s not a reliable, safe solution.<\/p>\n<p>We wanted to fix these issues and worked on introducing versioning for our <a href=\"https:\/\/developers.intercom.com\/building-apps\/docs\/rest-apis\" target=\"_blank\" rel=\"noopener noreferrer\">REST<\/a> and <a href=\"https:\/\/developers.intercom.com\/building-apps\/docs\/messenger-framework\" target=\"_blank\" rel=\"noopener noreferrer\">Messenger Framework<\/a> APIs. The enhanced creation and management of multiple releases of our API would not only improve our APIs as a platform but also improve the developer experience. We focused on providing a solution that reduces friction for developers by allowing them <a href=\"https:\/\/developers.intercom.com\/building-apps\/docs\/api-versioning\" target=\"_blank\" rel=\"noopener noreferrer\">to upgrade their apps<\/a> when they wish in a safe way.<\/p>\n<h2 id=\"listening-to-our-customers-needs\">Listening to our customers\u2019 needs<\/h2>\n<p>We wanted to identify the main friction points when developing apps and updating to the latest version of our API in order to minimize the complexity and the risk of the upgrades. So, we conducted research sessions with our users to understand how they use our platform APIs as well as other platforms and the main problems that they face.<\/p>\n<p>It became clear that developers need to be able to assess the changes in a single place with a very clear, in-depth <a href=\"https:\/\/developers.intercom.com\/building-apps\/v1.0\/docs\/api-changelog\" target=\"_blank\" rel=\"noopener noreferrer\">changelog<\/a>. They needed any changes to our API to fit their processes. We needed to allow them to plan upgrades with plenty of notice and provide them with very convenient and flexible ways to test their code before performing an upgrade, as well as enable them to roll back quickly if anything went wrong.<\/p>\n<h2 id=\"our-approach-to-api-versioning\">Our approach to API versioning<\/h2>\n<p>We have our own open source library, called <a href=\"https:\/\/github.com\/intercom\/requisite\" target=\"_blank\" rel=\"noopener noreferrer\">Requisite<\/a>, so we can strongly define request and response models for serialization in an elegant way. We use this library to implement our models. The simplified version of our <code><span style=\"background-color: #fdf1db;\">UserResponse<\/span><\/code> serializer, which transforms the internal user model to the API payload, looks like this:<\/p>\n<p><code style=\"line-height: 1;\"><span style=\"background-color: #fdf1db;\">class UserResponse<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 30px;\">serialized_attributes do<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 60px;\">attribute! :id<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 60px;\">attribute :user_id<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 60px;\">attribute :email<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 60px;\">attribute :phone<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 60px;\">attribute :name<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 30px;\">end<\/span><br \/>\n<span style=\"background-color: #fdf1db;\">End<\/span><\/code><\/p>\n<h3>Introducing version changes<\/h3>\n<p>Inspired by <a href=\"https:\/\/stripe.com\/blog\/api-versioning\" target=\"_blank\" rel=\"noopener noreferrer\">the Stripe API versioning blog post<\/a>, we introduced the concept of a <em>version change<\/em>, which represents a single change made on an API model. It consists of a description of the change, the public model it\u2019s targeting, and a transformation to the previous version of the model. Multiple <em>version changes<\/em> are compiled into a version.<\/p>\n<p>Our controllers always operate on the latest version of the models. If the API receives a request for an older version, we transform it into the requested version using the <em>version change<\/em>. We use the same transformations to parse request payloads from older versions to the latest one, with the only difference that we apply them in an ascending order.<\/p>\n<p><a href=\"https:\/\/www.intercom.com\/blog\/api-versioning\/api-versioning-diagram\/\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-18757 size-full\" src=\"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2018\/11\/API-versioning-diagram.jpeg\" alt=\"Diagram of how API versioning works in Intercom\" width=\"1920\" height=\"840\" srcset=\"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2018\/11\/API-versioning-diagram.jpeg 1920w, https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2018\/11\/API-versioning-diagram-300x131.jpeg 300w, https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2018\/11\/API-versioning-diagram-768x336.jpeg 768w, https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2018\/11\/API-versioning-diagram-700x306.jpeg 700w, https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2018\/11\/API-versioning-diagram-600x263.jpeg 600w, https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2018\/11\/API-versioning-diagram-1400x613.jpeg 1400w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/a><\/p>\n<h4>How a single version change works<\/h4>\n<p>If we want to rename the <em>user_id<\/em> on the <code><span style=\"background-color: #fdf1db;\">User<\/span><\/code> public model to <em>customer_id<\/em>, we would need to update the <code><span style=\"background-color: #fdf1db;\">UserResponse<\/span><\/code> model to use the new attribute and create a new <code><span style=\"background-color: #fdf1db;\">VersionChange<\/span><\/code> that transforms the payload back to the previous version.<\/p>\n<p><code><span style=\"background-color: #fdf1db;\">class UserResponse<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 30px;\">serialized_attributes do<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 60px;\">attribute! :id<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 60px;\">attribute :<strong>customer_id<\/strong><\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 60px;\">attribute :email<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 60px;\">attribute :phone<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 60px;\">attribute :name<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 30px;\">end<\/span><br \/>\n<span style=\"background-color: #fdf1db;\">End<\/span><\/code><\/p>\n<p><code><span style=\"background-color: #fdf1db;\">class RenameUserResponseCustomerId &lt; VersionChange<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 30px;\">description \"User model will now use customer_id instead of user_id\"<\/span><\/code><\/p>\n<p><code><span style=\"background-color: #fdf1db; padding-left: 30px;\">transform UserResponse do |data|<br \/>\n<span style=\"background-color: #fdf1db; padding-left: 60px;\">data.merge(user_id: data[:customer_id])<br \/>\n<span style=\"background-color: #fdf1db; padding-left: 30px;\">end<br \/>\n<span style=\"background-color: #fdf1db;\">end<\/span><\/span><\/span><\/span><\/code><\/p>\n<p>The idea here is that when we need to make a change, we always update our public models to the latest version and then use a <code><span style=\"background-color: #fdf1db;\">VersionChange<\/span><\/code> subclass to roll back that change and get the previous version of the public model. We then group multiple <code><span style=\"background-color: #fdf1db;\">VersionChanges<\/span><\/code> in a <code><span style=\"background-color: #fdf1db;\">Version<\/span><\/code>.<\/p>\n<p><code><span style=\"background-color: #fdf1db;\">VERSIONS = [<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 90px;\">Version.new(<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 120px;\">id: \"1.0\",<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 120px;\">changes: [<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 150px;\">InitialVersion,<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 120px;\">],<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 90px;\">),<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 90px;\">Version.new(<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 120px;\">id: \"1.1\",<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 120px;\">changes: [<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 150px;\">RenameUserResponseCustomerId,<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 150px;\">AllowSearchMultipleUsersByEmail,<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 120px;\">],<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 90px;\">),<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 60px;\">]<\/span><\/code><\/p>\n<h4>How we chain multiple version changes<\/h4>\n<p>It\u2019s possible to chain many <code><span style=\"background-color: #fdf1db;\">VersionChanges<\/span><\/code> for a public model and apply multiple transformations. This can happen if we have multiple <code><span style=\"background-color: #fdf1db;\">VersionChanges<\/span><\/code> on a single model in multiple versions.<\/p>\n<p>To expand on the previous example, if we decide to rename <em>customer_id<\/em> to <em>person_id<\/em> in version 1.2, we should update the <code><span style=\"background-color: #fdf1db;\">UserResponse<\/span><\/code> to use the new attribute, and add a <code><span style=\"background-color: #fdf1db;\">VersionChange<\/span><\/code> that transforms the payload from v1.2 format to the one expected by v1.1:<\/p>\n<p><code><span style=\"background-color: #fdf1db;\">class UserResponse<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 30px;\">serialized_attributes do<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 60px;\">attribute! :id<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 60px;\">attribute :<strong>person_id<\/strong><\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 60px;\">attribute :email<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 60px;\">attribute :phone<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 60px;\">attribute :name<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 30px;\">end<\/span><br \/>\n<span style=\"background-color: #fdf1db;\">End<\/span><\/code><\/p>\n<p><code><span style=\"background-color: #fdf1db;\">class RenameUserResponsePersonId &lt; VersionChange<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 30px;\">description \"User model will now use person_id instead of customer_id\"<\/span><\/code><\/p>\n<p><code><span style=\"background-color: #fdf1db; padding-left: 30px;\">transform UserResponse do |data|<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 60px;\">data.merge(customer_id: data[:person_id])<\/span><br \/>\n<span style=\"background-color: #fdf1db; padding-left: 30px;\">end<\/span><br \/>\n<span style=\"background-color: #fdf1db;\">end<\/span><\/code><\/p>\n<p>When a v1.0 request comes in, we first apply the <em>RenameUserResponsePersonId<\/em> transformation, which transforms it to v1.1. Then, we pass it to the <em>RenameUserResponseCustomerId<\/em> transformation, which transforms it into v1.0. This way, any response payload can be transformed into a version that the client expects.<\/p>\n<p>With our controllers only operating on the latest version, all the code related to previous versions is contained inside the <code><span style=\"background-color: #fdf1db;\">VersionChanges<\/span><\/code> objects. This design allows us to have a single implementation of the logic, eliminating duplicated code and reducing the extra overhead in the maintenance, making our codebase more robust, reliable and maintainable.<\/p>\n<h3>How API versioning works in practice<\/h3>\n<p>Adding the versioning allows us to implement feature requests and bug fixes that highly benefit a specific audience of developers without forcing everyone to upgrade. A clear example of this is searching by email in the Users endpoint of our REST API.<\/p>\n<p>In version 1.0, we can only return a single user when searching by email. If multiple users are associated with the same email address that endpoint returns an error. Even though this is not a desirable behavior, and the solution is simple to implement, some developers depend on it. A fix could break their apps. Their code expects response payloads in a specific format and will not be able to parse a list as a result.<\/p>\n<p>In <a href=\"https:\/\/developers.intercom.com\/building-apps\/docs\/api-changelog\" target=\"_blank\" rel=\"noopener noreferrer\">version 1.1<\/a>, we now support fetching multiple users with the same email. Every developer can opt-in to using this version when their code is ready to support it.<\/p>\n<blockquote class=\"pullquote-style-one\"><p>&#8220;We can now release changes to all our platform features more frequently and safely&#8221;<\/p><\/blockquote>\n<p>The design we followed makes our platform versions flexible and easy to test. We allow testing isolated requests using a specific header to ensure that the app works well with the new functionality before updating its version. When everything is tested, updating through the <a href=\"https:\/\/app.intercom.com\/a\/apps\/_\/developer-hub\" target=\"_blank\" rel=\"noopener noreferrer\">Developer Hub<\/a> will make all the requests and responses coming from this app to be interpreted in the new version.<\/p>\n<p>Rolling back in case of a problem is also immediate through the same process. We can now release changes to all our platform features, like REST API, Messenger Framework and webhooks, more frequently and safely. This allows us to improve the quality of our platform and therefore the apps built on top of it.<\/p>\n<h2 id=\"shipping-fast-and-growing-a-platform\">Shipping fast and growing a platform<\/h2>\n<p>Developing APIs to support fast growing products comes with a lot of challenges. This felt like a particular constraint at a company where shipping software fast and often is integral to how we work and build products. We wanted to enable Intercom engineers to support our APIs better. By implementing versioning, we\u2019re now able to align ourselves with the rest of our engineering team and to ship continuously.<\/p>\n<p>Ultimately, if the old version of our APIs was like a contract that required careful renegotiation every time we wanted to make an improvement, implementing versioning frees us from that \u2013 now we can improve and iterate on our APIs much more dynamically, with all parties able to feel secure and confident in the process.<\/p>\n<p><em><strong>Additional contributor:<\/strong>\u00a0<a href=\"https:\/\/twitter.com\/gabanca\" target=\"_blank\" rel=\"noopener noreferrer\">Gabriel Anca Corral<\/a> works as a product engineer at Intercom.<\/em><\/p>\n<p><em>\u00a0<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Developing APIs to support developers building on top of our fast growing products comes with a lot of challenges. At Intercom, we have now introduced API versioning to enable us to improve and iterate on our platform more dynamically and safely.<\/p>\n","protected":false},"author":294,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"category":[12898],"tags":[242,11510],"coauthors":[1174,13034],"class_list":["post-18744","post","type-post","status-publish","format-standard","hentry","category-engineering","tag-apis","tag-developers"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.3 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Growing A Platform: Introducing API Versioning In Intercom<\/title>\n<meta name=\"description\" content=\"Developing APIs to support developers building on top of our fast growing products comes with a lot of challenges. At Intercom, we have now introduced API versioning to enable us to improve and iterate on our platform more dynamically and safely.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.intercom.com\/blog\/api-versioning\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Growing a platform: Introducing API versioning in Intercom\" \/>\n<meta property=\"og:description\" content=\"Developing APIs to support developers building on top of our fast growing products comes with a lot of challenges. At Intercom, we have now introduced API versioning to enable us to improve and iterate on our platform more dynamically and safely.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.intercom.com\/blog\/api-versioning\/\" \/>\n<meta property=\"og:site_name\" content=\"The Intercom Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/intercominc\" \/>\n<meta property=\"article:published_time\" content=\"2018-11-29T16:19:30+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-07-30T11:55:24+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2018\/11\/API-versioning-diagram.jpeg\" \/>\n<meta name=\"author\" content=\"Sofia Tzima, Marin Martinic\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@intercom\" \/>\n<meta name=\"twitter:site\" content=\"@intercom\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Sofia Tzima, Marin Martinic\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/api-versioning\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/api-versioning\\\/\"},\"author\":{\"name\":\"Sofia Tzima\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#\\\/schema\\\/person\\\/cd6a931251cfe3a2d96234d1650f9489\"},\"headline\":\"Growing a platform: Introducing API versioning in Intercom\",\"datePublished\":\"2018-11-29T16:19:30+00:00\",\"dateModified\":\"2020-07-30T11:55:24+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/api-versioning\\\/\"},\"wordCount\":1344,\"publisher\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/api-versioning\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/wp-content\\\/uploads\\\/2018\\\/11\\\/API-versioning-diagram.jpeg\",\"keywords\":[\"APIs\",\"developers\"],\"articleSection\":[\"Engineering\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/api-versioning\\\/\",\"url\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/api-versioning\\\/\",\"name\":\"Growing A Platform: Introducing API Versioning In Intercom\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/api-versioning\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/api-versioning\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/wp-content\\\/uploads\\\/2018\\\/11\\\/API-versioning-diagram.jpeg\",\"datePublished\":\"2018-11-29T16:19:30+00:00\",\"dateModified\":\"2020-07-30T11:55:24+00:00\",\"description\":\"Developing APIs to support developers building on top of our fast growing products comes with a lot of challenges. At Intercom, we have now introduced API versioning to enable us to improve and iterate on our platform more dynamically and safely.\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.intercom.com\\\/blog\\\/api-versioning\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/api-versioning\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/wp-content\\\/uploads\\\/2018\\\/11\\\/API-versioning-diagram.jpeg\",\"contentUrl\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/wp-content\\\/uploads\\\/2018\\\/11\\\/API-versioning-diagram.jpeg\",\"width\":1920,\"height\":840,\"caption\":\"Diagram of how API versioning works in Intercom\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/\",\"name\":\"The Intercom Blog\",\"description\":\"Articles and Podcasts on Customer Service, AI and Automation, Product, and more\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#organization\",\"name\":\"The Intercom Blog\",\"url\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/08\\\/Intercom-logo-sq-black-trans.png\",\"contentUrl\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/08\\\/Intercom-logo-sq-black-trans.png\",\"width\":1000,\"height\":1000,\"caption\":\"The Intercom Blog\"},\"image\":{\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/intercominc\",\"https:\\\/\\\/x.com\\\/intercom\",\"https:\\\/\\\/www.instagram.com\\\/intercom\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/2491343\",\"https:\\\/\\\/www.pinterest.ie\\\/intercom\\\/\",\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UCJG0MvLP03kyzzAkD-w98aQ\",\"https:\\\/\\\/en.wikipedia.org\\\/wiki\\\/Intercom_(company)\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/#\\\/schema\\\/person\\\/cd6a931251cfe3a2d96234d1650f9489\",\"name\":\"Sofia Tzima\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c3d4e8ef7d50cee70b593ad9743b54b1438642d4d769b63ac18dcae0c7c39b5a?s=96&d=mm&r=pg58b14177b61f8fac2b49bb7119f6104a\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c3d4e8ef7d50cee70b593ad9743b54b1438642d4d769b63ac18dcae0c7c39b5a?s=96&d=mm&r=pg\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c3d4e8ef7d50cee70b593ad9743b54b1438642d4d769b63ac18dcae0c7c39b5a?s=96&d=mm&r=pg\",\"caption\":\"Sofia Tzima\"},\"description\":\"Former Product Engineer, Intercom. Mainly backend focused engineer with an interest in APIs and integrations but has worked full stack throughout her career. You can find more writing by Sofia at her Medium page.\",\"url\":\"https:\\\/\\\/www.intercom.com\\\/blog\\\/author\\\/sophiesiw\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Growing A Platform: Introducing API Versioning In Intercom","description":"Developing APIs to support developers building on top of our fast growing products comes with a lot of challenges. At Intercom, we have now introduced API versioning to enable us to improve and iterate on our platform more dynamically and safely.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.intercom.com\/blog\/api-versioning\/","og_locale":"en_US","og_type":"article","og_title":"Growing a platform: Introducing API versioning in Intercom","og_description":"Developing APIs to support developers building on top of our fast growing products comes with a lot of challenges. At Intercom, we have now introduced API versioning to enable us to improve and iterate on our platform more dynamically and safely.","og_url":"https:\/\/www.intercom.com\/blog\/api-versioning\/","og_site_name":"The Intercom Blog","article_publisher":"https:\/\/www.facebook.com\/intercominc","article_published_time":"2018-11-29T16:19:30+00:00","article_modified_time":"2020-07-30T11:55:24+00:00","og_image":[{"url":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2018\/11\/API-versioning-diagram.jpeg","type":"","width":"","height":""}],"author":"Sofia Tzima, Marin Martinic","twitter_card":"summary_large_image","twitter_creator":"@intercom","twitter_site":"@intercom","twitter_misc":{"Written by":"Sofia Tzima, Marin Martinic","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.intercom.com\/blog\/api-versioning\/#article","isPartOf":{"@id":"https:\/\/www.intercom.com\/blog\/api-versioning\/"},"author":{"name":"Sofia Tzima","@id":"https:\/\/www.intercom.com\/blog\/#\/schema\/person\/cd6a931251cfe3a2d96234d1650f9489"},"headline":"Growing a platform: Introducing API versioning in Intercom","datePublished":"2018-11-29T16:19:30+00:00","dateModified":"2020-07-30T11:55:24+00:00","mainEntityOfPage":{"@id":"https:\/\/www.intercom.com\/blog\/api-versioning\/"},"wordCount":1344,"publisher":{"@id":"https:\/\/www.intercom.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.intercom.com\/blog\/api-versioning\/#primaryimage"},"thumbnailUrl":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2018\/11\/API-versioning-diagram.jpeg","keywords":["APIs","developers"],"articleSection":["Engineering"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.intercom.com\/blog\/api-versioning\/","url":"https:\/\/www.intercom.com\/blog\/api-versioning\/","name":"Growing A Platform: Introducing API Versioning In Intercom","isPartOf":{"@id":"https:\/\/www.intercom.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.intercom.com\/blog\/api-versioning\/#primaryimage"},"image":{"@id":"https:\/\/www.intercom.com\/blog\/api-versioning\/#primaryimage"},"thumbnailUrl":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2018\/11\/API-versioning-diagram.jpeg","datePublished":"2018-11-29T16:19:30+00:00","dateModified":"2020-07-30T11:55:24+00:00","description":"Developing APIs to support developers building on top of our fast growing products comes with a lot of challenges. At Intercom, we have now introduced API versioning to enable us to improve and iterate on our platform more dynamically and safely.","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.intercom.com\/blog\/api-versioning\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.intercom.com\/blog\/api-versioning\/#primaryimage","url":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2018\/11\/API-versioning-diagram.jpeg","contentUrl":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2018\/11\/API-versioning-diagram.jpeg","width":1920,"height":840,"caption":"Diagram of how API versioning works in Intercom"},{"@type":"WebSite","@id":"https:\/\/www.intercom.com\/blog\/#website","url":"https:\/\/www.intercom.com\/blog\/","name":"The Intercom Blog","description":"Articles and Podcasts on Customer Service, AI and Automation, Product, and more","publisher":{"@id":"https:\/\/www.intercom.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.intercom.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.intercom.com\/blog\/#organization","name":"The Intercom Blog","url":"https:\/\/www.intercom.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.intercom.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2019\/08\/Intercom-logo-sq-black-trans.png","contentUrl":"https:\/\/www.intercom.com\/blog\/wp-content\/uploads\/2019\/08\/Intercom-logo-sq-black-trans.png","width":1000,"height":1000,"caption":"The Intercom Blog"},"image":{"@id":"https:\/\/www.intercom.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/intercominc","https:\/\/x.com\/intercom","https:\/\/www.instagram.com\/intercom\/","https:\/\/www.linkedin.com\/company\/2491343","https:\/\/www.pinterest.ie\/intercom\/","https:\/\/www.youtube.com\/channel\/UCJG0MvLP03kyzzAkD-w98aQ","https:\/\/en.wikipedia.org\/wiki\/Intercom_(company)"]},{"@type":"Person","@id":"https:\/\/www.intercom.com\/blog\/#\/schema\/person\/cd6a931251cfe3a2d96234d1650f9489","name":"Sofia Tzima","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/c3d4e8ef7d50cee70b593ad9743b54b1438642d4d769b63ac18dcae0c7c39b5a?s=96&d=mm&r=pg58b14177b61f8fac2b49bb7119f6104a","url":"https:\/\/secure.gravatar.com\/avatar\/c3d4e8ef7d50cee70b593ad9743b54b1438642d4d769b63ac18dcae0c7c39b5a?s=96&d=mm&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/c3d4e8ef7d50cee70b593ad9743b54b1438642d4d769b63ac18dcae0c7c39b5a?s=96&d=mm&r=pg","caption":"Sofia Tzima"},"description":"Former Product Engineer, Intercom. Mainly backend focused engineer with an interest in APIs and integrations but has worked full stack throughout her career. You can find more writing by Sofia at her Medium page.","url":"https:\/\/www.intercom.com\/blog\/author\/sophiesiw\/"}]}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/posts\/18744","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/users\/294"}],"replies":[{"embeddable":true,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/comments?post=18744"}],"version-history":[{"count":0,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/posts\/18744\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/media?parent=18744"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/category?post=18744"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/tags?post=18744"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.intercom.com\/blog\/wp-json\/wp\/v2\/coauthors?post=18744"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}