{"id":990,"date":"2025-11-06T16:19:57","date_gmt":"2025-11-07T00:19:57","guid":{"rendered":"https:\/\/embedded.gusto.com\/blog\/?p=990"},"modified":"2025-12-02T10:34:55","modified_gmt":"2025-12-02T18:34:55","slug":"defensive-programming-api-clients","status":"publish","type":"post","link":"https:\/\/embedded.gusto.com\/blog\/defensive-programming-api-clients\/","title":{"rendered":"Defensive Programming: A Guide to Building Resilient API Clients"},"content":{"rendered":"<p>Imagine this: it\u2019s payday, and your system calls a payroll application programming interface (API) to process salaries. The request times out, so your client retries it. However, the initial request actually went through, but you just didn\u2019t receive the confirmation. Suddenly, every employee is double-paid, or worse, no one gets paid at all. One small glitch on the network level just turned into a very expensive mistake that can cause serious financial and compliance issues.<\/p>\n<p>Thankfully, defensive programming can help. Instead of assuming that everything works as expected, defensive programming involves writing API clients that anticipate failures and protect against them. Networks are unreliable, services have downtimes, and bugs happen, but a resilient client treats these as the norm, not an exception. By designing with failure in mind, you can avoid critical errors, like duplicate charges, missed payments, or cascading retries that overwhelm a service.<\/p>\n<p>In this guide, you\u2019ll learn techniques for building resilient API clients. You\u2019ll learn how to implement retries safely using exponential backoff, why idempotent requests are important, and how modern APIs like <a href=\"https:\/\/embedded.gusto.com\/\">Gusto<\/a> use <a href=\"https:\/\/docs.gusto.com\/embedded-payroll\/docs\/api-fundamentals#reliability\"><code class=\"\" data-line=\"\">Idempotency Keys<\/code> and \u2018Optimistic Version Control\u2019 <\/a> to prevent operations from being executed twice.<\/p>\n<h2 id=\"understand-why-defensive-programming-matters-for-api-clients\">Understand Why Defensive Programming Matters for API Clients<\/h2>\n<p>We all know APIs don\u2019t run in perfect environments. Failures are not only possible but expected. You see everything from transient network drops and <code class=\"\" data-line=\"\">HTTP 500<\/code> errors under peak load to rate-limit responses like <code class=\"\" data-line=\"\">HTTP 429 Too Many Requests<\/code>. Even DNS resolution failures or partial timeouts can cause requests to hang indefinitely. Even with robust infrastructure, no API can guarantee 100 percent uptime or consistency. If your API client design assumes success by default, one minor issue can break your integration and ripple through the rest of your system.<\/p>\n<p>In domains with high stakes like payroll, defensive programming is even more important. If retries aren\u2019t handled correctly, duplicate adjustments or repeated tax withholdings can occur, leading to inaccurate payroll results. These issues can harm trust, create compliance risks, and be costly to fix.<\/p>\n<p>A defensive mindset is critical to building resilient API clients. Instead of assuming every request succeeds, assume the requests may be lost, delayed, or duplicated. Design each interaction with the expectation of failure. When you plan for failure at every step, your client can keep functioning gracefully even when the API or network is unpredictable.<\/p>\n<h2 id=\"build-resilient-api-clients-using-defensive-programming\">Build Resilient API Clients Using Defensive Programming<\/h2>\n<p>Resilient API clients aren\u2019t built with a single technique but through a set of practices designed to predict and contain failure.<\/p>\n<h3 id=\"handle-failures-correctly-with-retries\">Handle Failures Correctly with Retries<\/h3>\n<p>Retries are the primary tool developers reach for when dealing with unreliable APIs. The idea is this: if a request fails, send it again. However, not all failures are created equal, and retrying blindly can do more harm than good.<\/p>\n<h4 id=\"manage-transient-and-permanent-failures\">Manage Transient and Permanent Failures<\/h4>\n<p>Before retrying after an error, you need to decide whether you should retry or stop and fail fast. The distinction between transient and permanent failures helps guide that logic.<\/p>\n<p>Transient errors are faults that may resolve on their own if you try again. Examples include network timeouts, service overloads, or temporary outages in downstream systems. In HTTP, you often see status codes like <a href=\"https:\/\/docs.gusto.com\/embedded-payroll\/docs\/error-categories#internal_error\"><code class=\"\" data-line=\"\">500 Internal Server Error<\/code><\/a>, <code class=\"\" data-line=\"\">502 Bad Gateway<\/code>, <a href=\"https:\/\/docs.gusto.com\/embedded-payroll\/docs\/error-categories#third_party_service_unavailable\"><code class=\"\" data-line=\"\">503 Service Unavailable<\/code><\/a>, or even <code class=\"\" data-line=\"\">504 Gateway Timeout<\/code>. These are signals that the server isn\u2019t able to fulfill the request right now, but may be able to later. In these cases, retrying makes sense, provided you back off appropriately.<\/p>\n<p>A special case worth mentioning is <a href=\"https:\/\/docs.gusto.com\/embedded-payroll\/docs\/error-categories#rate_limit_exceeded\"><code class=\"\" data-line=\"\">429 Too Many Requests<\/code><\/a>. This indicates that your client has hit a rate limit. While it\u2019s technically a transient error, you shouldn\u2019t retry immediately. Instead, check the <code class=\"\" data-line=\"\">Retry-After<\/code> header in the response (if present) and wait for the specified duration before sending another request. This ensures your client respects server limits and avoids being throttled further.<\/p>\n<p>Permanent errors reflect problems that can\u2019t be resolved with a retry. These include <code class=\"\" data-line=\"\">400 Bad Request<\/code>, <code class=\"\" data-line=\"\">401 Unauthorized<\/code>, <a href=\"https:\/\/docs.gusto.com\/embedded-payroll\/docs\/error-categories#missing_oauth_scopes\"><code class=\"\" data-line=\"\">403 Forbidden<\/code><\/a>, <a href=\"https:\/\/docs.gusto.com\/embedded-payroll\/docs\/error-categories#not_found\"><code class=\"\" data-line=\"\">404 Not Found<\/code><\/a>, and <a href=\"https:\/\/docs.gusto.com\/embedded-payroll\/docs\/error-categories#duplicate_operation\"><code class=\"\" data-line=\"\">422 Unprocessable Entity<\/code><\/a> due to invalid parameters. Once one of these errors is returned, retrying is futile. Instead, your client should fail fast and surface the error for intervention.<\/p>\n<h4 id=\"prevent-the-risk-of-naive-retry-strategies\">Prevent the Risk of Naive Retry Strategies<\/h4>\n<p>Naive retry strategies can introduce new problems. If every client retries immediately after a timeout, the server can become overwhelmed by a surge of duplicate requests. Even worse, a poorly designed client can execute the same operation twice, leading to unintended side effects, like submitting the same payroll run multiple times. Error handling must go beyond simply trying again.<\/p>\n<h4 id=\"combine-exponential-backoff-with-jitter\">Combine Exponential Backoff with Jitter<\/h4>\n<p>To avoid these pitfalls, the industry standard is to combine exponential backoff with jitter. Exponential backoff spaces out each retry by increasing the delay each time: wait one second, then two, then four, then eight, and so on. Jitter adds a random variation to these wait times, ensuring multiple clients don\u2019t retry at the same time and overwhelm the server.<\/p>\n<p>Here\u2019s a simple Python example showing exponential backoff with jitter when calling an API endpoint. This example uses a <code class=\"\" data-line=\"\">GET<\/code> request for simplicity. The same retry logic applies to <code class=\"\" data-line=\"\">POST<\/code>, <code class=\"\" data-line=\"\">PUT<\/code>, <code class=\"\" data-line=\"\">PATCH<\/code>, and <code class=\"\" data-line=\"\">DELETE<\/code> operations as well. Just make sure those operations are idempotent before retrying so that multiple attempts do not cause unintended side effects:<\/p>\n<pre class=\" language-py\"><code class=\"\" data-line=\"\">\n```py\nimport requests\nimport time\nimport random\n\ndef make_request_with_retries(url, max_retries=5):\n   last_exception = None\n\n   for attempt in range(max_retries):\n       try:\n           response = requests.get(\n               url,\n               headers={\n                   &quot;accept&quot;: &quot;application\/json&quot;,\n                   &quot;X-Gusto-API-Version&quot;: &quot;2025-06-15&quot;,\n                   &quot;authorization&quot;: &quot;Bearer &lt;YOUR-COMPANY-API-TOKEN&gt;&quot;\n               },\n               timeout=5\n           )\n           response.raise_for_status()\n           return response.json()\n      \n       except requests.exceptions.RequestException as e:\n           last_exception = e\n\n           # Don&#039;t retry on client errors like 400 or 401\n           if response is not None and 400 &lt;= e.response.status_code &lt; 500:\n               raise e\n          \n           # Don&#039;t sleep after the last attempt\n           if attempt &lt; max_retries - 1:\n               wait_time = (2 ** attempt) + random.uniform(0, 1)\n               print(f&quot;Retry {attempt + 1}\/{max_retries} failed: {e}. Retrying in {wait_time:.2f}s...&quot;)\n               time.sleep(wait_time)\n           else:\n               print(f&quot;Retry {attempt + 1}\/{max_retries} failed: {e}. Max retries reached.&quot;)\n  \n   raise last_exception or Exception(&quot;Max retries reached. Request failed.&quot;)\n\n# Example usage:\ndata = make_request_with_retries(&quot;https:\/\/api.gusto-demo.com\/v1\/payrolls\/&lt;PAYROLL_UUID&gt;\/receipt&quot;)\n```\n\n<\/code><\/pre>\n<p>This code attempts to <a href=\"https:\/\/docs.gusto.com\/embedded-payroll\/reference\/get-v1-payment-receipts-payrolls-payroll_uuid\">get a single payroll receipt<\/a> with increasing wait times between retries. Each failure triggers an exponential delay (one second, two seconds, four seconds, and so on) with a bit of randomness added (the jitter) to avoid synchronized retry attempts. If all attempts fail, it raises the last exception so that the calling code can log or handle it appropriately.<\/p>\n<h3 id=\"handle-idempotency-design-safe-retries\">Handle Idempotency: Design Safe Retries<\/h3>\n<p>Retries are only truly safe when they\u2019re paired with idempotency. In the context of APIs, idempotency means that a request can be executed multiple times but only produces the same outcome as the initial successful execution. It\u2019s the safeguard that prevents retries from accidentally causing duplicate side effects.<\/p>\n<p>In real-world systems, idempotency protects against the unpredictable behavior of networks and clients. Imagine a user submitting a payment form or signing up for an account, and their browser freezes midway. If they refresh and the client resends the same request, idempotency ensures the user isn\u2019t charged twice or created as a duplicate record (in cases where there are no unique identifiers, such as username or email).<\/p>\n<p>The most common way to achieve this is through a unique identifier that links all the attempts of a request to a single logical operation. Modern APIs, like the Gusto Embedded Payroll APIs, support this pattern with the <a href=\"https:\/\/docs.gusto.com\/embedded-payroll\/docs\/idempotency\"><code class=\"\" data-line=\"\">Idempotency-Key<\/code> header<\/a>. When a client submits a request with an idempotency key, the server stores both the request and its result. If the client retries with the same key against the same endpoint, the server doesn\u2019t run the operation again; it simply returns the previously stored result. Gusto takes this a step further through the use of version-based object management. For update operations, the API requires a <code class=\"\" data-line=\"\">version<\/code> field that helps prevent race conditions. If the resource has changed since the client\u2019s last request, the API returns a <code class=\"\" data-line=\"\">409 Conflict<\/code> instead of silently overwriting data. This guarantees that retries don\u2019t create conflicting state changes even under concurrent operations.<\/p>\n<p>This approach is especially important in payroll systems where correctness is important. Imagine creating a payroll run for your workforce. Without an idempotency key, a retry after a timeout may be interpreted as a second payroll run, leading to employees being double-paid and the company facing compliance issues. With idempotency in place, all retries are tied back to the same logical run, so employees are paid exactly once, no matter how many times the request is retried.<\/p>\n<p>Here\u2019s an example of how you can send a payroll creation request with an idempotency key header to guarantee safe retries:<\/p>\n<pre class=\" language-py\"><code class=\"\" data-line=\"\">\n```py\nimport uuid\nimport requests\n\ndef create_payroll(company_id, idempotency_key, payroll_data):\n   headers = {\n       &quot;Authorization&quot;: &quot;Bearer &lt;YOUR-COMPANY-ACCESS-TOKEN&gt;&quot;,\n       &quot;accept&quot;: &quot;application\/json&quot;,\n       &quot;X-Gusto-API-Version&quot;: &quot;2025-06-15&quot;,\n       &quot;Content-Type&quot;: &quot;application\/json&quot;,\n       &quot;Idempotency-Key&quot;: idempotency_key  # unique key for this operation,\n   }\n\n   url = f&quot;https:\/\/api.gusto-demo.com\/v1\/companies\/{company_id}\/payrolls&quot;\n  \n   response = requests.post(\n       url,\n       json=payroll_data,\n       headers=headers\n   )\n   response.raise_for_status()\n   return response.json()\n\n# Example usage\nidempotency_key = str(uuid.uuid4())\npayload = {\n  &quot;off_cycle&quot;: True,\n  &quot;off_cycle_reason&quot;: &quot;Bonus&quot;,\n  &quot;start_date&quot;: &quot;2025-11-11&quot;,\n  &quot;end_date&quot;: &quot;2025-11-18&quot;\n}\n\nresult = create_payroll(company_id=&#039;123&#039;, idempotency_key=idempotency_key, payroll_data=payload)\nprint(result)\n```\n\n<\/code><\/pre>\n<p>This code sends a <a href=\"https:\/\/docs.gusto.com\/embedded-payroll\/reference\/post-v1-companies-company_id-payrolls\">create payroll<\/a> request to Gusto while using an idempotency key to ensure safe retries. It generates a unique key with <code class=\"\" data-line=\"\">uuid.uuid4()<\/code> and passes it in the <code class=\"\" data-line=\"\">Idempotency-Key<\/code> header so the API can recognize repeat attempts as the same operation.<\/p>\n<h3 id=\"implement-resilient-api-client-patterns\">Implement Resilient API Client Patterns<\/h3>\n<p>Once you understand retries and idempotency, the next step is to apply them consistently. Resilient API clients aren\u2019t just a collection of one-off fixes; they\u2019re built around a set of design patterns that treat reliability as a core concern. These patterns assume that every request can fail, and they put safeguards in place so those failures never compromise correctness.<\/p>\n<p>Building resilience also means thinking beyond a single API call. In distributed systems, dependencies can go down, networks can degrade, and partial failures can ripple across services. Robust clients use techniques, such as fallback services (<em>eg<\/em> using cached data or a secondary endpoint when the primary is unavailable), graceful degradation (serving limited functionality instead of breaking completely), and circuit breakers to prevent cascading failures. Together with retries, timeouts, and idempotency, these techniques form the foundation of reliability in APIs.<\/p>\n<p>Here are the key patterns that guide the design of reliable API clients:<\/p>\n<table>\n<thead>\n<tr>\n<th>Pattern<\/th>\n<th>Why It Matters<\/th>\n<th>Example in Practice<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Treat every request as if it can fail.<\/td>\n<td>Networks and servers are inherently unreliable. Coding as if success is guaranteed leads to brittle integrations.<\/td>\n<td>Always implement timeouts, retries, and error handling logic.<\/td>\n<\/tr>\n<tr>\n<td>Ensure critical operations are idempotent.<\/td>\n<td>Without idempotency, retries can trigger duplicate side effects, like double payments.<\/td>\n<td>Use an <code class=\"\" data-line=\"\">Idempotency-Key<\/code> (or equivalent identifier) to safely retry operations. For example, Gusto supports this through the <code class=\"\" data-line=\"\">Idempotency-Key<\/code> header.<\/td>\n<\/tr>\n<tr>\n<td>Monitor and log retry behavior.<\/td>\n<td>Silent retries hide systemic issues. Visibility is needed for debugging and capacity planning.<\/td>\n<td>Record retry attempts and their outcomes in your client logs.<\/td>\n<\/tr>\n<tr>\n<td>Back off intelligently.<\/td>\n<td>Immediate retries amplify the load and risk further failure. Exponential backoff with jitter smooths traffic spikes.<\/td>\n<td>Retry requests with increasing wait times and randomized delays.<\/td>\n<\/tr>\n<tr>\n<td>Fail fast on permanent errors.<\/td>\n<td>Retrying invalid requests wastes resources and delays recovery.<\/td>\n<td>Stop retries when the API returns <code class=\"\" data-line=\"\">4xx<\/code> client errors like <code class=\"\" data-line=\"\">401 Unauthorized<\/code>.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>When applied together, these patterns transform an integration from fragile to dependable. Instead of breaking down under real-world conditions, the client absorbs failures, retries safely, and communicates clearly when something is wrong.<\/p>\n<h2 id=\"optimistic-version-control\">Optimistic Version Control<\/h2>\n<p>Another method of ensuring data integrity is utilizing optimistic version control. Object-based versions\u2014essentially snapshots of a given resource\u2014are used to process concurrent updates correctly, ensuring data integrity in a multi-user environment. It is a form of optimistic concurrency control, where the system \u2018assumes\u2019 that conflicts are rare and only checks for them at the time of an update.<\/p>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>Building resilient API clients means embracing the reality that things fail: networks drop, servers timeout, and dependencies falter. You need to anticipate these failures\u2014handle retries with exponential backoff and make requests idempotent so developers can ensure their integrations behave predictably, even under stress.<\/p>\n<p>This defensive mindset is especially important in payroll, where correctness and compliance are non-negotiable. Defensive programming protects both businesses and workers from outcomes that a simple integration would never catch.<\/p>\n<p>Beyond exposing payroll APIs, <a href=\"https:\/\/embedded.gusto.com\/\">Gusto Embedded<\/a> incorporates safeguards like idempotency support, compliance infrastructure, and reliability features that align with the best practices covered in this guide. By combining defensive programming techniques with the right platform, you can build API clients that are not only functional but also resilient.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Imagine this: it\u2019s payday, and your system calls a payroll application programming interface (API) to process salaries. The request times&#8230;<\/p>\n","protected":false},"author":33,"featured_media":991,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-990","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developer-perspective"],"acf":{"exclude_from_embedded_resources":true,"popularity":0,"essentiality":0},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Defensive Programming: A Guide to Building Resilient API Clients - Embedded Blog<\/title>\n<meta name=\"description\" content=\"Defensive programming involves writing API clients that anticipate failures and protect against them to reduce errors.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/embedded.gusto.com\/blog\/defensive-programming-api-clients\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Defensive Programming: A Guide to Building Resilient API Clients - Embedded Blog\" \/>\n<meta property=\"og:description\" content=\"Defensive programming involves writing API clients that anticipate failures and protect against them to reduce errors.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/embedded.gusto.com\/blog\/defensive-programming-api-clients\/\" \/>\n<meta property=\"og:site_name\" content=\"Embedded Blog\" \/>\n<meta property=\"article:published_time\" content=\"2025-11-07T00:19:57+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-12-02T18:34:55+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/embeddedblog.wpengine.com\/wp-content\/uploads\/2025\/11\/Defensive-Programming-Blog-1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1920\" \/>\n\t<meta property=\"og:image:height\" content=\"1080\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Kevin Kimani\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Kevin Kimani\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Defensive Programming: A Guide to Building Resilient API Clients - Embedded Blog","description":"Defensive programming involves writing API clients that anticipate failures and protect against them to reduce errors.","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:\/\/embedded.gusto.com\/blog\/defensive-programming-api-clients\/","og_locale":"en_US","og_type":"article","og_title":"Defensive Programming: A Guide to Building Resilient API Clients - Embedded Blog","og_description":"Defensive programming involves writing API clients that anticipate failures and protect against them to reduce errors.","og_url":"https:\/\/embedded.gusto.com\/blog\/defensive-programming-api-clients\/","og_site_name":"Embedded Blog","article_published_time":"2025-11-07T00:19:57+00:00","article_modified_time":"2025-12-02T18:34:55+00:00","og_image":[{"width":1920,"height":1080,"url":"https:\/\/embeddedblog.wpengine.com\/wp-content\/uploads\/2025\/11\/Defensive-Programming-Blog-1.png","type":"image\/png"}],"author":"Kevin Kimani","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Kevin Kimani","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/embedded.gusto.com\/blog\/defensive-programming-api-clients\/#article","isPartOf":{"@id":"https:\/\/embedded.gusto.com\/blog\/defensive-programming-api-clients\/"},"author":{"name":"Kevin Kimani","@id":"https:\/\/embedded.gusto.com\/blog\/#\/schema\/person\/78940c23d5d19587854ca6c0018375dd"},"headline":"Defensive Programming: A Guide to Building Resilient API Clients","datePublished":"2025-11-07T00:19:57+00:00","dateModified":"2025-12-02T18:34:55+00:00","mainEntityOfPage":{"@id":"https:\/\/embedded.gusto.com\/blog\/defensive-programming-api-clients\/"},"wordCount":1849,"image":{"@id":"https:\/\/embedded.gusto.com\/blog\/defensive-programming-api-clients\/#primaryimage"},"thumbnailUrl":"https:\/\/embeddedblog.wpengine.com\/wp-content\/uploads\/2025\/11\/Defensive-Programming-Blog-1.png","articleSection":["Developer Perspective"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/embedded.gusto.com\/blog\/defensive-programming-api-clients\/","url":"https:\/\/embedded.gusto.com\/blog\/defensive-programming-api-clients\/","name":"Defensive Programming: A Guide to Building Resilient API Clients - Embedded Blog","isPartOf":{"@id":"https:\/\/embedded.gusto.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/embedded.gusto.com\/blog\/defensive-programming-api-clients\/#primaryimage"},"image":{"@id":"https:\/\/embedded.gusto.com\/blog\/defensive-programming-api-clients\/#primaryimage"},"thumbnailUrl":"https:\/\/embeddedblog.wpengine.com\/wp-content\/uploads\/2025\/11\/Defensive-Programming-Blog-1.png","datePublished":"2025-11-07T00:19:57+00:00","dateModified":"2025-12-02T18:34:55+00:00","author":{"@id":"https:\/\/embedded.gusto.com\/blog\/#\/schema\/person\/78940c23d5d19587854ca6c0018375dd"},"description":"Defensive programming involves writing API clients that anticipate failures and protect against them to reduce errors.","breadcrumb":{"@id":"https:\/\/embedded.gusto.com\/blog\/defensive-programming-api-clients\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/embedded.gusto.com\/blog\/defensive-programming-api-clients\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/embedded.gusto.com\/blog\/defensive-programming-api-clients\/#primaryimage","url":"https:\/\/embeddedblog.wpengine.com\/wp-content\/uploads\/2025\/11\/Defensive-Programming-Blog-1.png","contentUrl":"https:\/\/embeddedblog.wpengine.com\/wp-content\/uploads\/2025\/11\/Defensive-Programming-Blog-1.png","width":1920,"height":1080,"caption":"defensive programming of API clients"},{"@type":"BreadcrumbList","@id":"https:\/\/embedded.gusto.com\/blog\/defensive-programming-api-clients\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/embedded.gusto.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Defensive Programming: A Guide to Building Resilient API Clients"}]},{"@type":"WebSite","@id":"https:\/\/embedded.gusto.com\/blog\/#website","url":"https:\/\/embedded.gusto.com\/blog\/","name":"Embedded Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/embedded.gusto.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/embedded.gusto.com\/blog\/#\/schema\/person\/78940c23d5d19587854ca6c0018375dd","name":"Kevin Kimani","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/embeddedblog.wpengine.com\/wp-content\/uploads\/2025\/11\/kevin-author-draftdev-150x150.webp","url":"https:\/\/embeddedblog.wpengine.com\/wp-content\/uploads\/2025\/11\/kevin-author-draftdev-150x150.webp","contentUrl":"https:\/\/embeddedblog.wpengine.com\/wp-content\/uploads\/2025\/11\/kevin-author-draftdev-150x150.webp","caption":"Kevin Kimani"},"description":"Kevin Kimani is a passionate developer and technical writer who enjoys explaining complicated concepts in a simple way.","url":"https:\/\/embedded.gusto.com\/blog\/author\/draftdev-kevinkimani\/"}]}},"images":{"large":"https:\/\/embeddedblog.wpengine.com\/wp-content\/uploads\/2025\/11\/Defensive-Programming-Blog-1-1120x630.png"},"authorDetails":{"id":33,"name":"Kevin Kimani","avatar":"https:\/\/embeddedblog.wpengine.com\/wp-content\/uploads\/2025\/11\/kevin-author-draftdev-150x150.webp"},"_links":{"self":[{"href":"https:\/\/embedded.gusto.com\/blog\/wp-json\/wp\/v2\/posts\/990","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/embedded.gusto.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/embedded.gusto.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/embedded.gusto.com\/blog\/wp-json\/wp\/v2\/users\/33"}],"replies":[{"embeddable":true,"href":"https:\/\/embedded.gusto.com\/blog\/wp-json\/wp\/v2\/comments?post=990"}],"version-history":[{"count":0,"href":"https:\/\/embedded.gusto.com\/blog\/wp-json\/wp\/v2\/posts\/990\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/embedded.gusto.com\/blog\/wp-json\/wp\/v2\/media\/991"}],"wp:attachment":[{"href":"https:\/\/embedded.gusto.com\/blog\/wp-json\/wp\/v2\/media?parent=990"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/embedded.gusto.com\/blog\/wp-json\/wp\/v2\/categories?post=990"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/embedded.gusto.com\/blog\/wp-json\/wp\/v2\/tags?post=990"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}