Join now

Discount for all plans 40%

Join Now
Skip to content
BUILD IT
HomePricing

BuildGazette Developer API

Read-only access to articles, series, frameworks, BI Executive docs, lab questions, mentors, and authors. Plus-plan users mint keys at /account; webhook endpoints at /account/webhooks.

Quick start

Send the key in Authorization: Bearer <bi_…>. Every response carries X-Request-Id and X-RateLimit-* headers.

curl https://buildgazette.com/api/v1/articles \
  -H "Authorization: Bearer YOUR_BI_KEY" \
  -H "Accept: application/json"

Spec: openapi.jsonopenapi.yamlpostman.jsonTypeScript SDKPython SDK

Authentication

Keys carry a bi_ prefix and are matched against a SHA-256 hash on every request. Plaintext is held in an AES-256-GCM vault and may be revealed up to three times after creation. Rotation mints a new key and revokes the old one after a 24-hour overlap (or immediately via POST /api/api-keys/{id}/rotate?immediate=true for compromise scenarios).

  • Per-key origin and CIDR-aware IP allowlists.
  • Constant-time hash comparison; invalid keys throttled per source IP.
  • Revealing burns one of three views; after that the plaintext is wiped from the vault and the key becomes show-once.

Scopes

Each endpoint declares a required scope. Keys carry an array of granted scopes from this whitelist; unknown values are silently dropped on save. Scope violations return 403 insufficient_scope.

ScopeCovers
blogs.readArticles, categories, search
series.readSeries + parts
frameworks.readFramework catalog + details
bi.readBI Executive documents
lab.readCommunity lab questions
mentor.readMentor profiles
author.readAuthor profiles + recent posts
feed.readPersonal feed
analytics.readPer-key call analytics
analytics.read.aggregateAnonymized aggregate analytics
topics.readTopic landing data
community.readPublic community profiles
me.readProfile of the key owner

Rate limits

Two layers stack on every call:

  • Sliding window — 60 requests / 60 seconds, per key.
  • Daily quotadaily_call_limit (default 1,000), reset at 00:00 UTC. Bumped per-key on request.

Each successful response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (Unix seconds). On 429, Retry-After is set in seconds. Build your client to back off when remaining drops to zero rather than after a 429.

Idempotency

For non-GET endpoints (when introduced), send Idempotency-Key: <your-token>. Identical body + path + key within 24 hours replays the original 2xx response and adds an Idempotent-Replay: true header. Errors are never cached.

curl -X POST "https://buildgazette.com/api/v1/widgets" \
  -H "Authorization: Bearer YOUR_BI_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"name":"alpha"}'

Error envelope

All errors return application/problem+json with this shape — the request_id matches the X-Request-Id response header, quote it in support tickets.

{
  "error": {
    "code": "insufficient_scope",
    "type": "https://buildgazette.com/developers#errors-insufficient-scope",
    "title": "Insufficient Scope",
    "status": 403,
    "message": "Required scope: blogs.read",
    "doc_url": "https://buildgazette.com/developers#errors-insufficient-scope",
    "request_id": "f5b3..."
  }
}
CodeHTTPMeaning
missing_api_key401No Authorization header sent
invalid_api_key401Key not found, revoked, or malformed
origin_not_allowed403Origin not in the per-key allowlist
ip_not_allowed403Caller IP not in the per-key allowlist
insufficient_scope403Key lacks the required scope
rate_limited429Per-key sliding window exhausted (60/min)
daily_quota_exceeded429Daily call cap hit, resets 00:00 UTC
not_found404Resource does not exist or is unpublished
invalid_query400A required query parameter is missing/invalid
query_failed500Internal database error — retry, then contact support
internal_error500Unexpected server error; include X-Request-Id

Webhooks

Register HTTPS endpoints at /account/webhooks. Every delivery is signed using HMAC-SHA256 over canonical JSON (sorted keys) of the payload, with the timestamp embedded in the header.

# Header sent on every delivery
X-BuildGazette-Signature: t=1700000000,v1=<hex>
X-BuildGazette-Signature-Version: v1
X-BuildGazette-Event: article.published
X-BuildGazette-Delivery: <uuid>

Verification (Node):

import { createHmac } from 'crypto';

function verify(req, secret) {
  const sig = req.headers['x-buildgazette-signature']; // 't=...,v1=...'
  const parts = Object.fromEntries(sig.split(',').map(p => p.split('=')));
  const expected = createHmac('sha256', secret)
    .update(`${parts.t}.${req.rawBody}`)
    .digest('hex');
  return expected === parts.v1
    && Math.abs(Date.now()/1000 - Number(parts.t)) < 300; // <5min drift
}

Retry schedule: 1m → 5m → 30m → 4h → 24h → 24h, ±20% jitter. After 20 consecutive failures the endpoint is auto-disabled — re-enable via PATCH { "is_active": true }. Per-endpoint filters are supported (e.g. only fire article.published events when data.category === 'engineering').

Code samples

JavaScript (fetch)

const res = await fetch(
  'https://buildgazette.com/api/v1/articles?limit=5',
  { headers: { Authorization: 'Bearer ' + process.env.BG_KEY }}
);
const { data } = await res.json();

Python (requests)

import os, requests
r = requests.get(
  'https://buildgazette.com/api/v1/articles',
  params={'limit': 5},
  headers={'Authorization': f"Bearer {os.environ['BG_KEY']}"},
)
r.raise_for_status()
data = r.json()['data']

TypeScript SDK

// curl https://buildgazette.com/api/v1/sdk/typescript > bg.ts
import { BuildGazette } from './bg';
const bg = new BuildGazette({ apiKey: process.env.BG_KEY! });
const { data } = await bg.callArticles({ limit: '5' });