{"id":1035,"date":"2025-10-04T23:18:28","date_gmt":"2025-10-05T06:18:28","guid":{"rendered":"https:\/\/www.alerainfotech.com\/home\/?p=1035"},"modified":"2025-10-05T11:56:37","modified_gmt":"2025-10-05T18:56:37","slug":"1035","status":"publish","type":"post","link":"https:\/\/www.alerainfotech.com\/home\/2025\/10\/04\/1035\/","title":{"rendered":""},"content":{"rendered":"\n<meta name=\"description\" content=\"Staff Engineer deep dive: architecting a scalable, PCI-compliant eCommerce payments platform with Java, Spring Boot, Kafka and PostgreSQL on AWS. Covers payment flows, tokenization, idempotency, SAGA refunds, and gateway integration.\">\n\n\n\n<div class=\"wp-block-cover is-dark\" style=\"min-height:320px;aspect-ratio:unset;\">\n<span aria-hidden=\"true\" class=\"wp-block-cover__background has-black-background-color has-background-dim\"><\/span>\n<div class=\"wp-block-cover__inner-container is-layout-flow wp-block-cover-is-layout-flow\">\n\n<h1 class=\"has-text-align-center has-white-color has-text-color wp-block-heading\" style=\"font-size:clamp(25.984px, 1.624rem + ((1vw - 3.2px) * 2.047), 44px);\">Staff Engineer Deep Dive: Building a Modern eCommerce Payments Platform (Java + Spring Boot + Kafka)<\/h1>\n\n\n<p class=\"has-text-align-center has-white-color has-text-color\">Part 1 \u2014 Gateway architecture, PCI-DSS, tokenization, idempotent checkout, and SAGA-based refunds.<\/p>\n\n<\/div><\/div>\n\n\n\n<p><strong>By Alera Infotech Engineering<\/strong> | October 2025<\/p>\n\n\n\n<p>Payments systems live at the intersection of <strong>throughput, irreversibility, and regulation<\/strong>. This guide walks Staff-level engineers through building a <strong>fault-tolerant, PCI-aware eCommerce payments platform<\/strong> using <strong>Java + Spring Boot + Kafka + PostgreSQL (AWS)<\/strong>. We focus on <em>determinism<\/em> (exactly-once outcomes), <em>auditability<\/em>, and <em>evolution<\/em> (how the system scales and changes safely).<\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">1) Responsibilities at Staff Level (Fintech\/eCommerce)<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Correctness over cleverness:<\/strong> payment state machines with provable invariants.<\/li>\n\n\n\n<li><strong>Reliability:<\/strong> API p99 &lt; 300 ms, monthly availability \u2265 99.95%, RPO \u2264 1 s, RTO \u2264 3 min.<\/li>\n\n\n\n<li><strong>PCI-DSS boundary design:<\/strong> keep PAN (card number) out of your core systems using tokenization.<\/li>\n\n\n\n<li><strong>Observability:<\/strong> distributed tracing, ledger\/audit correlation, error budget discipline.<\/li>\n\n\n\n<li><strong>Evolution:<\/strong> migrations, feature flags, backward\/forward compatibility, multi-gateway routing.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">2) System Overview (High-Level Flow)<\/h2>\n\n\n\n<p><strong>Checkout Service \u2192 Payments API \u2192 Orchestrator \u2192 Gateway Adapters (Stripe\/Adyen\/Razorpay\/etc.) \u2192 Risk\/Fraud \u2192 Ledger \u2192 Webhooks &amp; Notifications \u2192 Reconciliation<\/strong>. Kafka connects services; Outbox pattern guarantees exactly-once event publication.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Core Services<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Payments API (Spring MVC\/WebFlux):<\/strong> REST entry-point; validates, authorizes, idempotency.<\/li>\n\n\n\n<li><strong>Orchestrator:<\/strong> state machine for authorize\/capture\/void\/refund; invokes Gateway Adapters.<\/li>\n\n\n\n<li><strong>Gateway Adapters:<\/strong> one per PSP; maps unified API to vendor-specific schemas.<\/li>\n\n\n\n<li><strong>Risk\/Fraud:<\/strong> velocity, device, geolocation; fast rules + async ML (optional Part 2).<\/li>\n\n\n\n<li><strong>Ledger:<\/strong> append-only accounting; transactions &amp; entries with double-entry invariants.<\/li>\n\n\n\n<li><strong>Reconciliation:<\/strong> match gateway settlement files to ledger; raise diffs.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">3) PCI-DSS &amp; Tokenization Boundary<\/h2>\n\n\n\n<p><strong>Goal:<\/strong> keep Primary Account Number (PAN) out of your environment. Let the Payment Service Provider (PSP) or a PCI vault handle card data. Your systems operate on <em>tokens<\/em>.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Hosted fields\/checkout:<\/strong> card data posted directly to PSP \u2192 returns a <code>card_token<\/code>.<\/li>\n\n\n\n<li><strong>Your DB:<\/strong> store only <em>card_token<\/em>, last4, brand, expiry, BIN metadata (non-sensitive).<\/li>\n\n\n\n<li><strong>Encryption:<\/strong> HSM\/KMS for any secrets; rotate \u2264 90 days.<\/li>\n\n\n\n<li><strong>Vaulting:<\/strong> for network tokens (Visa\/MC) and card-on-file recurring payments.<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Design the PCI boundary so that a breach of your app <em>does not<\/em> disclose PAN. This is the single highest-leverage architectural decision in eCommerce.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">4) Idempotent Checkout API (Spring Boot)<\/h2>\n\n\n\n<p>Idempotency ensures retries (client\/network) don\u2019t double-charge. We rely on a client-supplied <code>Idempotency-Key<\/code> spanning the entire authorization or capture request. Store request\/response hash keyed by the idempotency key.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Controller + Idempotency Filter (Java)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ build.gradle (snippets)\n\/\/ implementation 'org.springframework.boot:spring-boot-starter-web'\n\/\/ implementation 'org.springframework.boot:spring-boot-starter-validation'\n\/\/ implementation 'org.springframework.kafka:spring-kafka'\n\/\/ implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'\n\/\/ implementation 'org.postgresql:postgresql'\n\n\/\/ IdempotencyFilter.java\n@Component\n@Order(1)\npublic class IdempotencyFilter implements Filter {\n  @Autowired IdempotencyStore store; \/\/ e.g., Redis or Postgres\n\n  @Override\n  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)\n      throws IOException, ServletException {\n    HttpServletRequest http = (HttpServletRequest) req;\n    HttpServletResponse httpRes = (HttpServletResponse) res;\n    String key = http.getHeader(\"Idempotency-Key\");\n    if (key == null || key.isBlank()) { chain.doFilter(req, res); return; }\n\n    Optional&lt;String&gt; prior = store.getResponse(key);\n    if (prior.isPresent()) {\n      httpRes.setHeader(\"Idempotency-Replayed\", \"true\");\n      httpRes.getWriter().write(prior.get());\n      return;\n    }\n\n    ContentCachingResponseWrapper wrapper = new ContentCachingResponseWrapper(httpRes);\n    chain.doFilter(req, wrapper);\n    String body = new String(wrapper.getContentAsByteArray(), StandardCharsets.UTF_8);\n    store.save(key, body);\n    wrapper.copyBodyToResponse();\n  }\n}\n\n\/\/ PaymentsController.java\n@RestController\n@RequestMapping(\"\/payments\")\npublic class PaymentsController {\n\n  @Autowired PaymentService service;\n\n  @PostMapping(\"\/authorize\")\n  public ResponseEntity&lt;PaymentAuthResponse&gt; authorize(@Valid @RequestBody PaymentAuthRequest req,\n                                       @RequestHeader(value=\"Idempotency-Key\", required=false) String idemKey) {\n    return ResponseEntity.ok(service.authorize(req, idemKey));\n  }\n}<\/code><\/pre>\n\n\n\n<p><strong>Notes:<\/strong> Persist the response JSON (plus request hash) under <code>Idempotency-Key<\/code>. For safety, scope keys to <code>merchantId<\/code> + <code>customerId<\/code>. Expire keys (e.g., 24\u201348h) to bound storage.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5) Orchestration &amp; Gateway Adapters<\/h2>\n\n\n\n<p>The Orchestrator implements the <strong>payment state machine<\/strong> and calls Gateway Adapters. Adapters map your internal DTOs to each PSP\u2019s API, handle errors, and normalize responses (auth code, AVS\/CVV results, 3DS status).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">State Machine (Authorize \u2192 Capture \u2192 Settle)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>New<\/strong> \u2192 <strong>Authorized<\/strong> (hold funds)<\/li>\n\n\n\n<li><strong>Authorized<\/strong> \u2192 <strong>Captured<\/strong> (charge)<\/li>\n\n\n\n<li><strong>Captured<\/strong> \u2192 <strong>Settled<\/strong> (PSP\/bank clears)<\/li>\n\n\n\n<li>Error paths: <strong>Void<\/strong> (release hold), <strong>Refund<\/strong> (partial\/full), <strong>Chargeback<\/strong><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Outbox Event After DB Commit<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>@Transactional\npublic PaymentAuthResponse authorize(PaymentAuthRequest r, String idemKey) {\n  Payment p = repo.createAuthorized(r); \/\/ authorizations table\n  \/\/ call adapter\n  GatewayAuthResult g = gatewayAdapter.authorize(r);\n  repo.updateWithGateway(p.getId(), g);\n  outbox.storeEvent(\"payment.authorized\", p.getId(), g); \/\/ same TX commit\n  return PaymentAuthResponse.from(p, g);\n}<\/code><\/pre>\n\n\n\n<p>The <em>Outbox<\/em> write occurs in the same DB transaction as the authorization record. A background publisher emits the event to Kafka after commit, ensuring exactly-once publication.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">6) Refunds &amp; Reversals with SAGA<\/h2>\n\n\n\n<p>Refunds span multiple systems (your DB, PSP, notifications). Implement a <strong>SAGA<\/strong> with compensations: if the PSP call succeeds but notification fails, you must still record the refund and schedule retries \u2014 do not roll back the bank.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Refund Saga Steps<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Create <code>refund_requested<\/code> row \u2192 emit <code>refund.requested<\/code>.<\/li>\n\n\n\n<li>Call PSP <code>refund()<\/code> (idempotent with <code>Idempotency-Key<\/code>).<\/li>\n\n\n\n<li>On success: mark <code>refund_completed<\/code> + ledger entries (negative amount).<\/li>\n\n\n\n<li>Emit <code>refund.completed<\/code> \u2192 send email\/notification.<\/li>\n\n\n\n<li>Compensations: if PSP declines after ledger write (rare if coded right), create <code>ledger reversal<\/code> and alert ops.<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>public void refund(String paymentId, Money amount) {\n  Refund r = repo.createRefund(paymentId, amount); \/\/ state = REQUESTED\n  try {\n    GatewayRefundResult gr = adapter.refund(paymentId, amount, r.getId()); \/\/ pass refund id as idem\n    repo.markRefundCompleted(r.getId(), gr);\n    ledger.postRefund(paymentId, amount, r.getId()); \/\/ append-only, negative entry\n    outbox.storeEvent(\"refund.completed\", r.getId(), gr);\n  } catch (GatewayDeclined e) {\n    repo.markRefundFailed(r.getId(), e.getCode());\n    outbox.storeEvent(\"refund.failed\", r.getId(), Map.of(\"reason\", e.getCode()));\n  }\n}<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>SAGA rule: <em>never<\/em> attempt to \u201cundo\u201d a bank transaction by deleting rows. Use <strong>compensating entries<\/strong> in the ledger. Money moves are append-only.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<div class=\"wp-block-cover is-dark\" style=\"min-height:200px;aspect-ratio:unset;\">\n<span aria-hidden=\"true\" class=\"wp-block-cover__background has-black-background-color has-background-dim\"><\/span>\n<div class=\"wp-block-cover__inner-container is-layout-flow wp-block-cover-is-layout-flow\">\n\n<h2 class=\"has-text-align-center has-white-color has-text-color wp-block-heading\" style=\"font-size:clamp(22.041px, 1.378rem + ((1vw - 3.2px) * 1.586), 36px);\">Part 2 \u2014 Ledger &amp; Reconciliation, Fraud, Observability, SLOs, Scale &amp; DR<\/h2>\n\n<\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">7) Ledger: Double-Entry Accounting &amp; Invariants<\/h2>\n\n\n\n<p>The ledger is the <em>source of truth<\/em> for money. Use <strong>double-entry<\/strong> (debits\/credits) with <em>append-only<\/em> entries. Never update historical rows; post adjustments. Keep <strong>transaction<\/strong> and <strong>entry<\/strong> tables separate.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Schema Sketch (PostgreSQL)<\/h3>\n\n\n<pre class=\"wp-block-code\"><code>-- transactions: logical money movements (auth, capture, refund)\nCREATE TABLE transactions (\n  id UUID PRIMARY KEY,\n  merchant_id UUID NOT NULL,\n  payment_id UUID NOT NULL,\n  type TEXT CHECK (type IN ('AUTH','CAPTURE','REFUND','FEE','CHARGEBACK')),\n  amount_cents BIGINT NOT NULL,\n  currency CHAR(3) NOT NULL,\n  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),\n  metadata JSONB\n);\n\n-- entries: double-entry postings that must net to zero per transaction\nCREATE TABLE entries (\n  id UUID PRIMARY KEY,\n  transaction_id UUID REFERENCES transactions(id),\n  account TEXT NOT NULL,         -- e.g., \"merchant_receivable\", \"psp_payable\", \"fees_income\"\n  direction TEXT CHECK (direction IN ('DEBIT','CREDIT')),\n  amount_cents BIGINT NOT NULL,\n  currency CHAR(3) NOT NULL,\n  created_at TIMESTAMPTZ NOT NULL DEFAULT now()\n);\n\n-- invariant: sum(entries.amount with sign) = 0 per transaction\n-- enforce via trigger or periodic assertion + reconciliation job<\/code><\/pre>\n\n\n\n<p><strong>Invariants:<\/strong> (1) Entries for a transaction must balance to zero; (2) No delete\/update of entries; (3) Currency must match across postings; (4) Referential integrity to payments\/refunds.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Posting Example (Capture)<\/h3>\n\n\n<ul class=\"wp-block-list\">\n<li>Debit <em>psp_receivable<\/em>, Credit <em>merchant_payable<\/em> (net of fees)<\/li>\n<li>Debit <em>merchant_payable<\/em>, Credit <em>cash<\/em> on settlement day<\/li>\n<li>Fee: Debit <em>merchant_payable<\/em>, Credit <em>fee_income<\/em><\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>The ledger protects you when gateways misbehave. If settlement files disagree, you can prove <em>exactly<\/em> what you believe about the money and why.<\/p><\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">8) Reconciliation: Matching PSP Files to Your Ledger<\/h2>\n\n\n\n<p>Each PSP provides daily settlement\/reconciliation files (CSV\/JSON\/SFTP). A reconciliation job ingests the file, normalizes rows, and matches them to your <code>transactions<\/code> and <code>entries<\/code>. Differences generate a <em>variance report<\/em> for ops, plus <code>recon.adjustment<\/code> entries if needed.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Workflow<\/h3>\n\n\n<ul class=\"wp-block-list\">\n<li>Ingest file \u2192 Staging table<\/li>\n<li>Join on <code>payment_id<\/code> \/ PSP reference \/ amount \/ currency<\/li>\n<li>Mark <code>matched<\/code>, <code>missing_in_psp<\/code>, or <code>missing_in_ledger<\/code><\/li>\n<li>Create adjustments as transactions with entries (append-only)<\/li>\n<li>Emit Kafka events \u2192 dashboards &amp; alerts<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">9) Fraud Signals &amp; Observability (Brief)<\/h2>\n\n\n\n<p><strong>Real-time rules:<\/strong> velocity per card\/email\/IP, BIN risk, country mismatch; <strong>Async ML:<\/strong> feature store + gRPC model. Log <em>reason codes<\/em> for every decision to support disputes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">RED Metrics &amp; Tracing<\/h3>\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Rate:<\/strong> TPS (transactions\/second) per endpoint and per gateway<\/li>\n<li><strong>Errors:<\/strong> 5xx rate, decline codes, idempotency replays<\/li>\n<li><strong>Duration:<\/strong> p50\/p90\/p99 latency for auth\/capture\/refund<\/li>\n<li><strong>Tracing:<\/strong> OpenTelemetry: propagate <code>trace_id<\/code> across API \u2192 Kafka \u2192 workers \u2192 ledger<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">10) Reliability Targets &amp; Error Budgets<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>SLOs:<\/strong> Auth p99 \u2264 300 ms, Capture p99 \u2264 350 ms, API availability \u2265 99.95 % (\u2248 22 min downtime\/month).<\/li>\n<li><strong>Error Budget:<\/strong> percentage of allowed failures (exhaustion \u2192 freeze risky changes, prioritize reliability).<\/li>\n<li><strong>RPO\/RTO:<\/strong> Recovery Point Objective \u2264 1 s (max data loss), Recovery Time Objective \u2264 3 min (time to restore).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Outbox, DLQ, and Replay<\/h3>\n\n\n<p><strong>Outbox:<\/strong> events written in-transaction; <strong>DLQ:<\/strong> permanent processing errors; <strong>Replay:<\/strong> reconcile by event idempotency keys. Expose DLQ age &amp; depth alarms.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">11) Throughput &amp; Cost Modeling<\/h2>\n\n\n\n<p>Assume average request \u2248 2 KB JSON, processing \u2248 300 ms. A single WebFlux instance on a c7g.2xlarge can handle ~300\u2013500 req\/s depending on GC &amp; I\/O. For 10k RPS sustained: ~25\u201335 instances (+ 20 % headroom). Batch workers scale horizontally via Kafka consumer groups.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Caching:<\/strong> Authorization lookups in Redis (TTL 60 s) \u2192 substantial p99 reduction.<\/li>\n<li><strong>Async I\/O:<\/strong> Prefer WebFlux + Reactor for gateway calls to use fewer threads.<\/li>\n<li><strong>Kafka:<\/strong> Partitions per topic sized to target consumer parallelism (start 3\u20135\u00d7 worker count).<\/li>\n<li><strong>DB:<\/strong> Partition <code>transactions<\/code> by month, index by (<code>merchant_id<\/code>, <code>created_at<\/code>), use logical replication for analytics.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">12) Multi-Region &amp; Disaster Recovery<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Active-Passive:<\/strong> Primary region + warm standby; Aurora Global Database or logical streaming; Route 53 failover; RPO \u2264 1 s, RTO \u2264 3 min.<\/li>\n<li><strong>Active-Active:<\/strong> Dual writers require conflict-free design (e.g., ledger with single-writer per money-bucket or XRIDs with deterministic merge). Use only if 99.99 % SLO or global low latency demands.<\/li>\n<li><strong>Kafka:<\/strong> MirrorMaker 2; checkpoint offsets per region; test consumer failover.<\/li>\n<li><strong>Chaos drills:<\/strong> quarterly region failover practice; verify DNS cutover and ledger consistency by checksums.<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Design DR so that the <em>same<\/em> idempotency key produces the <em>same<\/em> outcome regardless of region. Determinism beats heroics.<\/p><\/blockquote>\n\n\n<h2 class=\"wp-block-heading\">13) Putting It All Together (What to Say in a Staff Interview)<\/h2>\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Boundary:<\/strong> \u201cWe place the PCI boundary at the PSP; we store only tokens and metadata.\u201d<\/li>\n<li><strong>Determinism:<\/strong> \u201cIdempotency spans request\u2013response; outbox events are in-tx; SAGA handles refunds with compensating ledger entries.\u201d<\/li>\n<li><strong>Reliability:<\/strong> \u201cSLO 99.95 %, p99 auth \u2264 300 ms, RPO \u2264 1 s, RTO \u2264 3 min; DLQ age alarm at 15 min.\u201d<\/li>\n<li><strong>Evolution:<\/strong> \u201cAdapters hide PSP differences; feature flags + contract tests ensure zero-downtime migrations.\u201d<\/li>\n<li><strong>Traceability:<\/strong> \u201cEvery payment has a <code>trace_id<\/code> linking API, Kafka, ledger, and reconciliation.\u201d<\/li>\n<\/ul>\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n<p><em>\u00a9 2025 Alera Infotech Engineering | Tags: payments, java, spring boot, kafka, pci dss, idempotency, ledger, reconciliation, reliability<\/em><\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>By Alera Infotech Engineering | October 2025 Payments systems live at the intersection of throughput, irreversibility, and regulation. This guide walks Staff-level engineers through building a fault-tolerant, PCI-aware eCommerce payments platform using Java + Spring Boot + Kafka + PostgreSQL (AWS). We focus on determinism (exactly-once outcomes), auditability, and evolution (how the system scales and [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[],"class_list":["post-1035","post","type-post","status-publish","format-standard","hentry","category-careers"],"_links":{"self":[{"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/posts\/1035","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/comments?post=1035"}],"version-history":[{"count":2,"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/posts\/1035\/revisions"}],"predecessor-version":[{"id":1037,"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/posts\/1035\/revisions\/1037"}],"wp:attachment":[{"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/media?parent=1035"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/categories?post=1035"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/tags?post=1035"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}