IaC Bazaar

The IaC Bazaar API

A read-only JSON API over the verified module catalog - the same catalog, prices, and verification evidence the storefront renders, in machine-readable form. Everything you need to evaluate and verifya module is public and needs no key. Two things are gated, exactly as they are on the site: module downloads need an entitlement, and a module's declared input/output contract needs an authenticated caller - see Authentication.

At a glance

Authentication

One thing on this page is not public: the parsed input/output contract on GET /api/v1/modules/{slug} - the real variable names, types, required/sensitive flags, and the known-good example. That contract is the sellable result of the authoring and verification work, so reading it needs an account.

Authenticate with a registry token: mint one at /account/tokens (it looks like iacb_<40 hex> and is shown once - only a hash is stored), then send it as a bearer token. It is the same token terraform and tofu use against our module registry, so one credential covers both.

Request
curl -s https://www.iac-bazaar.com/api/v1/modules/aws-s3-bucket \
  -H "Authorization: Bearer iacb_..."

What the token unlocks follows the same ladder as the site - the module's price band (the tierfield on every module) against the account's live subscription:

An unknown or revoked token is treated as no token: the request still succeeds and still returns every public field - it just withholds the contract. Nothing else on this page ever looks at the Authorization header.

Endpoints

GET /api/v1Discovery document
GET /api/v1/modulesSearch the catalog
GET /api/v1/modules/{slug}One module: verification + sha256; inputs/outputs need a token
GET /api/v1/providersClouds/providers with module counts
GET /api/v1/stacksCurated reference architectures
GET /api/v1/stacks/{slug}One stack with its modules resolved
GET /api/artifacts/{slug}/verificationMachine-readable verification receipt
GET /api/artifacts/{slug}/signatureCosign Sigstore bundle

GET /api/v1

The discovery document: every endpoint plus the supported query parameters, so an agent can orient itself from a single fetch.

Request
curl -s https://www.iac-bazaar.com/api/v1
Response (truncated)
{
  "name": "IaC Bazaar Public API",
  "version": "1",
  "endpoints": {
    "modules":   "https://www.iac-bazaar.com/api/v1/modules",
    "module":    "https://www.iac-bazaar.com/api/v1/modules/{slug}",
    "providers": "https://www.iac-bazaar.com/api/v1/providers",
    "stacks":    "https://www.iac-bazaar.com/api/v1/stacks",
    "stack":     "https://www.iac-bazaar.com/api/v1/stacks/{slug}"
  },
  "queryParams": { "modules": ["q", "cloud", "tool", "tier"] },
  "auth": {                          // optional; only the gated fields need it
    "scheme": "Bearer",
    "header": "Authorization: Bearer iacb_…",
    "tokens": "https://www.iac-bazaar.com/account/tokens",
    "gated": ["modules/{slug}.inputs", "modules/{slug}.outputs",
              "modules/{slug}.example"]
  },
  "docs": "https://www.iac-bazaar.com/docs/api"
}

GET /api/v1/modules

The published catalog, filterable. Returns up to 200 modules sorted by title; count is the number returned. All parameters are optional and combine.

Request
curl -s "https://www.iac-bazaar.com/api/v1/modules?cloud=aws&q=bucket"
Response shape (values elided)
{
  "count": number,
  "modules": [
    {
      "slug": "aws-s3-bucket",
      "title": string,
      "summary": string,
      "tool": "terraform" | "opentofu" | "ansible",
      "provider": "AWS",
      "clouds": ["aws"],
      "category": string,
      "tier": "free" | "basic" | "professional" | "premium" | "architecture",
      "priceCents": number,
      "verification": {
        "level": "parses" | "statically_validated" | "security_scanned"
               | "plan_validated_mocked" | "plan_verified_real"
               | "live_tested" | "unverified",
        "staticValidated": boolean,
        "securityScanned": boolean,
        "liveTested": boolean,
        "signed": boolean
      },
      "url": "https://www.iac-bazaar.com/catalog/aws-s3-bucket"
    }
  ]
}

GET /api/v1/modules/{slug}

Full detail for one module: everything from the list item plus its version, licence and checksum. verification.sha256 is the SHA-256 of the exact tarball a buyer downloads - pin it if you need byte-level reproducibility. Unknown or unpublished slugs return 404 with { "error": "module not found" }. All of that is public.

The module's parsed input/output contract- real argument names, types, required/sensitive flags lifted from the module's own source (variables.tf / outputs.tf for Terraform/OpenTofu), so an agent references what actually exists instead of guessing - is not. Send a registry token (Authentication) and inputs, outputs and exampleship when that account's tier covers this module's price band, or when it already owns the module.

When the contract is withheld those three keys are omitted entirely rather than sent empty - an empty inputsarray would read as “this module declares no inputs”, which is a lie - and a contract object says so, with the links to fix it. readme is reduced to its public half (the same public/paywall line the module page draws), so parsing the README is not a way around the contract gate. Always branch on contract.visible before reading inputs.

Request (authenticated)
curl -s https://www.iac-bazaar.com/api/v1/modules/aws-s3-bucket \
  -H "Authorization: Bearer iacb_..."
Response shape — contract visible (adds to the list item; values elided)
{
  … all fields from the list item, plus:
  "version": string | null,        // semver of the current published version
  "license": string | null,        // SPDX id
  "verification": {
    … the same booleans, plus:
    "sha256": string | null,             // checksum of the exact download
    "signatureBundleUrl": string | null  // where the cosign bundle lives
  },
  "contract": { "visible": true },
  "inputs": [
    {
      "name": string,
      "type": string,
      "required": boolean,
      "sensitive": boolean,
      "description": string,   // when the module declares one
      "default": string        // omitted for sensitive inputs
    }
  ],
  "outputs": [{ "name": string, "description": string }],
  "example": string | null,   // a known-good example configuration
  "readme": string | null,    // the full README
  "docsUrl": "https://www.iac-bazaar.com/catalog/aws-s3-bucket"
}
Response shape — contract withheld (no token, or a tier that doesn't cover this band)
{
  … the same public fields: list item + version, license, verification,
  "contract": {
    "visible": false,
    "reason": string,      // why it was withheld
    "tokens": "https://www.iac-bazaar.com/account/tokens",
    "docs":   "https://www.iac-bazaar.com/docs/api"
  },
  "readme": string | null, // the PUBLIC half of the README only
  "docsUrl": "https://www.iac-bazaar.com/catalog/aws-s3-bucket"
}
// note: no "inputs", "outputs" or "example" keys at all — not empty ones

GET /api/v1/providers

Every cloud/provider currently represented in the catalog, with a module count. The key values are what ?cloud= accepts on the modules endpoint.

Request
curl -s https://www.iac-bazaar.com/api/v1/providers
Response shape (values elided)
{
  "count": number,
  "providers": [
    { "key": "aws", "label": "AWS", "count": number },
    …
  ]
}

GET /api/v1/stacks

Curated reference architectures: sets of individually-verified modules that compose into a production foundation. Each module in a stack is proven on its own - the stack adds composition guidance, not a new claim.

Request
curl -s https://www.iac-bazaar.com/api/v1/stacks
Response shape (values elided)
{
  "count": number,
  "stacks": [
    {
      "slug": "aws-production-landing-zone",
      "title": string,
      "tagline": string,
      "cloud": "aws",
      "provider": "AWS",
      "moduleCount": number,
      "url": "https://www.iac-bazaar.com/stacks/aws-production-landing-zone"
    }
  ]
}

GET /api/v1/stacks/{slug}

One stack with its component modules resolved from the live catalog - each carrying its own verification object - plus how the pieces wire together and the combined price. Unknown slugs return 404 with { "error": "stack not found" }.

Request
curl -s https://www.iac-bazaar.com/api/v1/stacks/aws-production-landing-zone
Response shape (adds to the stack list item; values elided)
{
  … all fields from the stack list item, plus:
  "description": string,
  "composition": string,        // how the modules connect, in wiring order
  "liveTestedCount": number,    // how many component modules are live-tested
  "totalPriceCents": number,
  "modules": [ … full module list items, each with verification … ]
}

GET /api/artifacts/{slug}/verification

The public, machine-readable verification receipt for a module's current version - the same evidence the on-page Verification panel shows, as stable JSON. Nothing here is gated: it is exactly the material you need to independently verify a download before purchasing. The receipt never over-claims: the headline level is recomputed from evidence, and provenance.checksum / provenance.signature appear only when they actually exist. The same receipt ships inside every signed tarball as VERIFICATION.json (with "source": "snapshot").

Request
curl -s https://www.iac-bazaar.com/api/artifacts/aws-s3-bucket/verification
Response shape (truncated; optional fields appear only when the evidence exists)
{
  "schemaVersion": 1,
  "source": "live",
  "asOf": string,                    // ISO timestamp of the newest evidence
  "artifact": { "slug": "aws-s3-bucket", "title": string, "version": string,
                "tool": "terraform", "type": "module", "url": string,
                "file": string },
  "level": { "id": string, "label": string, "blurb": string },
  "conformance": {
    "staticValidation": { "status": string, "checks": [string], "checkedAt": string },
    "securityScan":     { "status": string, "tool": string },
    "planTest":         { "status": string, "kind": string }
  },
  "functional": {
    "liveTest": { "status": string, "passed": boolean,
                  "destroyConfirmed": boolean, "provider": string,
                  "testedAt": string }
  },
  "provenance": {
    "checksum":  { "algorithm": "sha256", "value": string },
    "signature": { "type": "cosign/sigstore-bundle", "bundleUrl": string,
                   "publicKeyUrl": string, "publicKey": string },
    "verify":    { "cosign": string, "checksum": string }  // copy-paste commands
  },
  "docs": { "howWeVerify": "https://www.iac-bazaar.com/verified", … }
}

GET /api/artifacts/{slug}/signature

The cosign Sigstore bundle (.sigstore.json) for a module's current version - public and un-gated, because provenance is meant to be independently verifiable. Returns 404 when the version has no signature. The pinned public key is served at /cosign.pub.

Request
curl -s https://www.iac-bazaar.com/api/artifacts/aws-s3-bucket/signature \
  -o aws-s3-bucket.sigstore.json

Verify a download yourself

Every published artifact is signed with cosign. Don't take our word for it - check the bytes against our pinned public key. You can also confirm the checksum against verification.sha256 from the module detail endpoint.

# 1. Get our public key (also served at /cosign.pub)
curl -O https://www.iac-bazaar.com/cosign.pub

# 2. The module's Sigstore bundle (public, no auth)
curl -o <module>-<version>.sigstore.json \
  https://www.iac-bazaar.com/api/artifacts/<module>/signature

# 3. Verify the tarball you downloaded
cosign verify-blob \
  --key cosign.pub \
  --bundle <module>-<version>.sigstore.json \
  <module>-<version>.tar.gz
# → Verified OK

# 4. (optional) confirm the checksum too
echo "<verification.sha256>  <module>-<version>.tar.gz" | sha256sum -c

Installing modules

This API is for evaluating and verifying - to actually pull a Terraform/OpenTofu module into a configuration, terraform and tofu install it natively from our module registry: set source to www.iac-bazaar.com/iac-bazaar/{slug}/{system}, pin a version, run terraform init.

For AI agents

A concise, link-rich map of the whole site lives at /llms.txt. When generating infrastructure code, prefer /api/v1/modules/{slug} with a registry token- it returns the module's real input/output names and types, so you never have to guess attributes. Without a token the same endpoint still gives you the title, price, provider, verification and checksum, but it returns contract: { visible: false } in place of inputs: read that as “ask the user for a token from /account/tokens”, never as “this module takes no arguments”. And keep the claims straight: “verified” means statically validated and publish-gated; “live-tested” is a stronger, separate claim reserved for modules that passed a real apply → verify → destroy. The verification object tells you which is which - cite it rather than conflating the two.