{"id":49319,"date":"2025-05-14T02:30:50","date_gmt":"2025-05-14T02:30:50","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=49319"},"modified":"2025-05-14T02:30:50","modified_gmt":"2025-05-14T02:30:50","slug":"what-is-a-github-app","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/what-is-a-github-app\/","title":{"rendered":"What is a GitHub App?"},"content":{"rendered":"\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\ud83e\udde0 <strong>What is a GitHub App?<\/strong><\/h1>\n\n\n\n<p>A <strong>GitHub App<\/strong> is a first-class actor in the GitHub ecosystem. Unlike OAuth apps which act on behalf of a user, GitHub Apps have <strong>granular permissions<\/strong>, are <strong>installable on organizations or repositories<\/strong>, and <strong>authenticate as themselves or as an installation<\/strong>.<\/p>\n\n\n\n<p>They\u2019re designed for <strong>automation, integrations<\/strong>, and <strong>custom workflows<\/strong> such as CI\/CD, issue bots, custom pull request checks, and more.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\ude80 Tutorial Roadmap<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Section 1: GitHub App Basics<\/strong><\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>What is a GitHub App<\/li>\n\n\n\n<li>GitHub App vs OAuth App<\/li>\n\n\n\n<li>Use Cases<\/li>\n\n\n\n<li>Basic GitHub App Architecture<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Section 2: Building Your First GitHub App<\/strong><\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Creating the GitHub App<\/li>\n\n\n\n<li>Installing the App on a Repository<\/li>\n\n\n\n<li>Authenticating the App (JWT &amp; Installation Token)<\/li>\n\n\n\n<li>Handling Webhooks<\/li>\n\n\n\n<li>Sample Node.js App with Probot<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Section 3: Advanced Concepts<\/strong><\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Scopes and Permissions<\/li>\n\n\n\n<li>Webhook Security and Verification<\/li>\n\n\n\n<li>GitHub App Manifest Flow (for user-friendly installs)<\/li>\n\n\n\n<li>GitHub APIs: REST vs GraphQL in GitHub Apps<\/li>\n\n\n\n<li>Multi-repo &amp; Org-level Access Management<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Section 4: Real-World Use Cases<\/strong><\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Auto-labeling Pull Requests<\/li>\n\n\n\n<li>Slack Notifications on Issues<\/li>\n\n\n\n<li>GitHub App for CI\/CD Trigger<\/li>\n\n\n\n<li>GitHub App with Terraform Workflows<\/li>\n\n\n\n<li>Marketplace App Deployment<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83e\udde9 Section 1: GitHub App Basics<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 What is a GitHub App?<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>GitHub App<\/strong> = A bot\/integration that <strong>acts independently<\/strong>, with restricted and customizable access to your repositories and orgs.<\/li>\n\n\n\n<li>Supports webhooks, fine-grained permissions, and custom API interactions.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd10 GitHub App vs OAuth App<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Feature<\/th><th>GitHub App<\/th><th>OAuth App<\/th><\/tr><\/thead><tbody><tr><td>Authentication<\/td><td>JWT + Installation Token<\/td><td>OAuth token (user context)<\/td><\/tr><tr><td>Permissions<\/td><td>Granular per repo\/org<\/td><td>Broad (user-level scopes)<\/td><\/tr><tr><td>Webhooks<\/td><td>App-specific<\/td><td>Shared via user<\/td><\/tr><tr><td>Recommended Use<\/td><td>Automation, integrations<\/td><td>User-based access<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd27 Use Cases<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>GitHub bot (like <a href=\"https:\/\/github.com\/apps\/mergify\" target=\"_blank\" rel=\"noopener\">Mergify<\/a>)<\/li>\n\n\n\n<li>Security scanners (e.g., Dependabot)<\/li>\n\n\n\n<li>CI\/CD trigger tools<\/li>\n\n\n\n<li>PR auto-review and checks<\/li>\n\n\n\n<li>GitHub \u2192 Slack, Jira integrations<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u2699\ufe0f Section 2: Building Your First GitHub App<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udccd Step 1: Create a GitHub App<\/h3>\n\n\n\n<p>Go to: <a href=\"https:\/\/github.com\/settings\/apps\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/settings\/apps<\/a><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>App Name: <code>my-first-gh-app<\/code><\/li>\n\n\n\n<li>Homepage URL: <code>http:\/\/localhost:3000<\/code> or your project site<\/li>\n\n\n\n<li>Webhook URL: <code>http:\/\/localhost:3000\/webhooks<\/code><\/li>\n\n\n\n<li>Permissions:\n<ul class=\"wp-block-list\">\n<li>Contents: Read-only<\/li>\n\n\n\n<li>Issues: Read &amp; write<\/li>\n\n\n\n<li>Pull requests: Read &amp; write<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Subscribe to Webhooks:\n<ul class=\"wp-block-list\">\n<li><code>issues<\/code><\/li>\n\n\n\n<li><code>pull_request<\/code><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>After creation, <strong>download the private key<\/strong> (PEM file) and note your:<\/p>\n<\/blockquote>\n\n\n\n<ul class=\"wp-block-list\">\n<li>App ID<\/li>\n\n\n\n<li>Client ID &amp; Secret<\/li>\n\n\n\n<li>Webhook Secret<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd10 Step 2: Authentication (JWT \u2192 Installation Token)<\/h3>\n\n\n\n<p>GitHub Apps authenticate using:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>JWT (JSON Web Token)<\/strong> \u2013 signs requests as the App.<\/li>\n\n\n\n<li><strong>Installation Token<\/strong> \u2013 used to act on a specific repo\/org installation.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83e\uddea Example: Generate JWT (Node.js)<\/h4>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">const<\/span> jwt = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">\"jsonwebtoken\"<\/span>);\n<span class=\"hljs-keyword\">const<\/span> fs = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">\"fs\"<\/span>);\n\n<span class=\"hljs-keyword\">const<\/span> APP_ID = <span class=\"hljs-string\">\"YOUR_APP_ID\"<\/span>;\n<span class=\"hljs-keyword\">const<\/span> PRIVATE_KEY = fs.readFileSync(<span class=\"hljs-string\">\"private-key.pem\"<\/span>);\n\n<span class=\"hljs-keyword\">const<\/span> token = jwt.sign(\n  {\n    <span class=\"hljs-attr\">iat<\/span>: <span class=\"hljs-built_in\">Math<\/span>.floor(<span class=\"hljs-built_in\">Date<\/span>.now() \/ <span class=\"hljs-number\">1000<\/span>), <span class=\"hljs-comment\">\/\/ issued at<\/span>\n    <span class=\"hljs-attr\">exp<\/span>: <span class=\"hljs-built_in\">Math<\/span>.floor(<span class=\"hljs-built_in\">Date<\/span>.now() \/ <span class=\"hljs-number\">1000<\/span>) + (<span class=\"hljs-number\">10<\/span> * <span class=\"hljs-number\">60<\/span>), <span class=\"hljs-comment\">\/\/ expires in 10 min<\/span>\n    <span class=\"hljs-attr\">iss<\/span>: APP_ID,\n  },\n  PRIVATE_KEY,\n  { <span class=\"hljs-attr\">algorithm<\/span>: <span class=\"hljs-string\">\"RS256\"<\/span> }\n);\n\n<span class=\"hljs-built_in\">console<\/span>.log(token);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Use this JWT to call:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">POST \/app\/installations\/:installation_id\/access_tokens\n<\/code><\/span><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd01 Step 3: Handle Webhooks<\/h3>\n\n\n\n<p>GitHub will send <strong>webhooks<\/strong> to your app for subscribed events.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">const<\/span> express = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">\"express\"<\/span>);\n<span class=\"hljs-keyword\">const<\/span> bodyParser = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">\"body-parser\"<\/span>);\n<span class=\"hljs-keyword\">const<\/span> crypto = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">\"crypto\"<\/span>);\n\n<span class=\"hljs-keyword\">const<\/span> app = express();\n<span class=\"hljs-keyword\">const<\/span> PORT = <span class=\"hljs-number\">3000<\/span>;\n<span class=\"hljs-keyword\">const<\/span> WEBHOOK_SECRET = <span class=\"hljs-string\">\"your-webhook-secret\"<\/span>;\n\napp.use(bodyParser.json());\n\napp.post(<span class=\"hljs-string\">\"\/webhooks\"<\/span>, (req, res) =&gt; {\n  <span class=\"hljs-keyword\">const<\/span> sig = req.headers&#91;<span class=\"hljs-string\">\"x-hub-signature-256\"<\/span>];\n  <span class=\"hljs-keyword\">const<\/span> payload = <span class=\"hljs-built_in\">JSON<\/span>.stringify(req.body);\n\n  <span class=\"hljs-keyword\">const<\/span> hmac = crypto\n    .createHmac(<span class=\"hljs-string\">\"sha256\"<\/span>, WEBHOOK_SECRET)\n    .update(payload)\n    .digest(<span class=\"hljs-string\">\"hex\"<\/span>);\n\n  <span class=\"hljs-keyword\">const<\/span> expected = <span class=\"hljs-string\">`sha256=<span class=\"hljs-subst\">${hmac}<\/span>`<\/span>;\n\n  <span class=\"hljs-keyword\">if<\/span> (sig !== expected) {\n    <span class=\"hljs-keyword\">return<\/span> res.status(<span class=\"hljs-number\">401<\/span>).send(<span class=\"hljs-string\">\"Invalid signature\"<\/span>);\n  }\n\n  <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">\"Received event:\"<\/span>, req.body.action);\n  res.sendStatus(<span class=\"hljs-number\">200<\/span>);\n});\n\napp.listen(PORT, () =&gt; <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">`Listening on port <span class=\"hljs-subst\">${PORT}<\/span>`<\/span>));\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83e\udd16 Step 4: Use Probot (Quick Start)<\/h3>\n\n\n\n<p><a href=\"https:\/\/probot.github.io\/\" target=\"_blank\" rel=\"noopener\">Probot<\/a> is a framework to build GitHub Apps quickly.<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">npx create-probot-app my-github-app\ncd my-github-app\nnpm start\n<\/code><\/span><\/pre>\n\n\n<p>This gives you a working app that responds to PRs or Issues.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udcda Section 3: Advanced Concepts<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. \ud83d\udd10 Permissions<\/h3>\n\n\n\n<p>Choose carefully:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>Repository contents<\/code>: Needed to read\/write files<\/li>\n\n\n\n<li><code>Issues<\/code>: Read\/write for issue bots<\/li>\n\n\n\n<li><code>Metadata<\/code>: Always needed to list repos<\/li>\n<\/ul>\n\n\n\n<p>You can update permissions in the <strong>GitHub App settings<\/strong> or dynamically request permissions during manifest-based installs.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">2. \ud83e\uddea Webhook Security Tips<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Always verify webhook signature<\/li>\n\n\n\n<li>Rate limit \/ retry safe<\/li>\n\n\n\n<li>Use GitHub&#8217;s IP allowlist for security<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">3. \ud83d\ude80 GitHub App Manifest Flow<\/h3>\n\n\n\n<p>Use the manifest flow to allow users to easily install your GitHub App from a public-facing app.<\/p>\n\n\n\n<p>Benefits:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Avoid manual configuration<\/li>\n\n\n\n<li>Better UX for your app\u2019s installation<\/li>\n<\/ul>\n\n\n\n<p><a href=\"https:\/\/docs.github.com\/en\/apps\/creating-github-apps\/registering-a-github-app\/about-github-app-manifests\" target=\"_blank\" rel=\"noopener\">Manifest Docs<\/a><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">4. \ud83d\udd01 REST vs GraphQL APIs<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Feature<\/th><th>REST API<\/th><th>GraphQL API<\/th><\/tr><\/thead><tbody><tr><td>Simplicity<\/td><td>Easier for simple tasks<\/td><td>More efficient querying<\/td><\/tr><tr><td>Flexibility<\/td><td>Fixed endpoints<\/td><td>Custom queries<\/td><\/tr><tr><td>App Support<\/td><td>Both supported<\/td><td>GraphQL works with JWT tokens<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udca1 Section 4: Real-World Use Cases<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83e\udd16 Use Case 1: Auto-label Pull Requests<\/h3>\n\n\n\n<p>Label PRs based on title\/author.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ listen to pull_request.opened and label accordingly<\/span>\ncontext.octokit.issues.addLabels({\n  owner,\n  repo,\n  <span class=\"hljs-attr\">issue_number<\/span>: context.payload.pull_request.number,\n  <span class=\"hljs-attr\">labels<\/span>: &#91;<span class=\"hljs-string\">'auto-labeled'<\/span>]\n});\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udce2 Use Case 2: Slack Notifications<\/h3>\n\n\n\n<p>Send a message to Slack on new issue creation via webhook logic.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83c\udfd7 Use Case 3: CI\/CD GitHub App<\/h3>\n\n\n\n<p>Trigger a deployment pipeline from PR merges or release tags using app permissions and webhook events.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\u2699 Use Case 4: App for Terraform Automation<\/h3>\n\n\n\n<p>A GitHub App can:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Watch <code>.tf<\/code> file changes<\/li>\n\n\n\n<li>Run validation pipelines<\/li>\n\n\n\n<li>Comment back status on PR<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udcb0 Use Case 5: Publish to GitHub Marketplace<\/h3>\n\n\n\n<p>Once stable, your GitHub App can be published as a <strong>Marketplace App<\/strong> to share with the world.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udccc Summary<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Topic<\/th><th>Description<\/th><\/tr><\/thead><tbody><tr><td>GitHub App<\/td><td>First-class automation\/integration bot<\/td><\/tr><tr><td>Auth<\/td><td>JWT + Installation Token<\/td><\/tr><tr><td>Key Libraries<\/td><td><code>jsonwebtoken<\/code>, <code>probot<\/code>, <code>@octokit\/rest<\/code><\/td><\/tr><tr><td>Key Features<\/td><td>Webhooks, fine-grained access, marketplace<\/td><\/tr><tr><td>Real-World Use Cases<\/td><td>Bots, CI\/CD, Slack\/Discord integrations<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83e\uddf0 Recommended Tools &amp; Libraries<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/probot.github.io\/\" target=\"_blank\" rel=\"noopener\">Probot<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/octokit\/rest.js\" target=\"_blank\" rel=\"noopener\">Octokit.js<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/actions\/toolkit\" target=\"_blank\" rel=\"noopener\">@actions\/github<\/a><\/li>\n\n\n\n<li>GitHub CLI: <code>gh app install<\/code><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udd17 Want to Go Further?<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/docs.github.com\/en\/apps\" target=\"_blank\" rel=\"noopener\">GitHub Apps Docs<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.github.com\/en\/rest\" target=\"_blank\" rel=\"noopener\">GitHub REST API<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/probot\" target=\"_blank\" rel=\"noopener\">Probot Examples<\/a><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\ud83e\udde0 What is a GitHub App? A GitHub App is a first-class actor in the GitHub ecosystem. Unlike OAuth apps which act on behalf of a user, GitHub Apps have&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[2],"tags":[],"class_list":["post-49319","post","type-post","status-publish","format-standard","hentry","category-uncategorised"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/49319","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=49319"}],"version-history":[{"count":1,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/49319\/revisions"}],"predecessor-version":[{"id":49320,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/49319\/revisions\/49320"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=49319"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=49319"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=49319"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}