Apier.no Infrastructure API

Non-product endpoints (health checks, discovery).

Operations 3

GET /api/health Health check endpoint #
POST /api/webhooks/stripe Stripe billing webhook (server-to-server) #
POST /api/billing/topup-requests/{id}/resolve Approve or decline an agent top-up request (human, dashboard session) #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/apier-no:apier-no-infrastructure-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

apier-no-infrastructure-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Apier No Infrastructure API
  version: 1.0.13
  contact:
    name: Apier Support
    email: hello@apier.no
    url: https://www.apier.no
  license:
    name: Proprietary
  x-schema-org:
    description: Schema.org structured data for this service is emitted as application/ld+json on every SSR HTML page. The graph contains Organization, SoftwareApplication, WebAPI, and Service nodes. AI crawlers that read this OpenAPI document can cross-reference by fetching the site root and parsing the application/ld+json block in the document head.
    types:
    - Organization
    - SoftwareApplication
    - WebAPI
    - Service
    source: ''
  description: 'Operations tagged Infrastructure across 2 of this provider''s published API definitions: apier-no-openapi.json, apier-no-openapi.json. Each path carries the servers of the definition it was published in.'
servers:
- url: https://www.apier.no
  description: Production
security:
- BearerAuth: []
tags:
- name: Infrastructure
  description: Non-product endpoints (health checks, discovery).
paths:
  /api/health:
    get:
      summary: Health check endpoint
      description: Returns the service status and current server timestamp. This endpoint is used by external uptime monitoring (Betterstack). It is intentionally outside the /v1/ namespace as an infrastructure endpoint that must remain stable across API version bumps.
      operationId: healthCheck
      tags:
      - Infrastructure
      security: []
      responses:
        '200':
          description: Service is healthy.
          content:
            application/json:
              schema:
                type: object
                required:
                - status
                - timestamp
                properties:
                  status:
                    type: string
                    enum:
                    - ok
                    description: Service status.
                  timestamp:
                    type: string
                    format: date-time
                    description: Current server time in ISO 8601 UTC.
              examples:
                healthy:
                  value:
                    status: ok
                    timestamp: '2026-04-16T10:30:00.000Z'
    servers:
    - url: https://www.apier.no
      description: Production
  /api/webhooks/stripe:
    post:
      summary: Stripe billing webhook (server-to-server)
      description: 'Stripe-signed webhook for billing lifecycle events. Handled events: checkout.session.completed (links the Stripe customer/subscription ids to the consumer, or — for sessions marked metadata.kind=credit_topup — grants prepaid credits exactly once), customer.subscription.created and customer.subscription.updated (map the subscription''s price and status to the consumer''s billing tier via the shared decision logic, including the past_due grace window), customer.subscription.deleted (downgrades the consumer to the free tier and sends a cancellation-confirmation email), charge.dispute.created (Sentry alert only — never a billing-state mutation), invoice.paid (sends a receipt email), and invoice.payment_failed (sends a payment-failed email; tier changes remain owned by the subscription events and the shared tier-decision logic). Lifecycle emails are exactly-once via a billing email ledger claim, so redeliveries and reconciliation re-runs can never re-send one. Called ONLY by Stripe and authenticated by the Stripe-Signature header — it is NOT a public or agent-facing surface, requires no Apier API key, and is intentionally outside the /api/v1 namespace (so the API-key auth model, response-provenance, and scope rules do not apply). A missing or invalid signature returns 400; the request body is never logged or echoed. Deliveries are idempotent at the database level (the Stripe event id is a primary key): a duplicate of a processed event is acknowledged with 200 and does no further work, while a delivery whose earlier run failed after the claim is re-run before acknowledging.'
      operationId: stripeBillingWebhook
      tags:
      - Infrastructure
      security: []
      parameters:
      - name: Stripe-Signature
        in: header
        required: true
        description: Stripe webhook signature header, verified against STRIPE_WEBHOOK_SECRET via the Stripe SDK before any processing. The signature is computed over the exact raw request bytes.
        schema:
          type: string
      requestBody:
        required: true
        description: Raw Stripe Event payload. The exact bytes are required for signature verification — the endpoint must not re-serialize the body before verifying.
        content:
          application/json:
            schema:
              type: object
              description: Opaque Stripe Event object (see the Stripe API reference). Apier verifies the signature, then acts only on a small allowlist of subscription event types; all other types are acknowledged and ignored.
      responses:
        '200':
          description: Event received and acknowledged — handled, ignored (unhandled type), or skipped as an already-processed duplicate. Stripe treats any 2xx as a successful delivery.
          content:
            application/json:
              schema:
                type: object
                required:
                - received
                properties:
                  received:
                    type: boolean
                    enum:
                    - true
                    description: Always true once the signature is verified and the event is recorded.
              examples:
                success:
                  summary: Example response
                  value:
                    received: true
        '400':
          description: The Stripe-Signature header was missing or failed verification. The request body and the underlying error are never logged or echoed.
          content:
            application/json:
              schema:
                type: object
                required:
                - success
                - error_code
                - explanation
                properties:
                  success:
                    type: boolean
                    enum:
                    - false
                    description: Always false on error.
                  error_code:
                    type: string
                    enum:
                    - MISSING_SIGNATURE
                    - INVALID_SIGNATURE
                    description: Machine-readable failure code.
                  explanation:
                    type: object
                    required:
                    - summary
                    properties:
                      summary:
                        type: string
                        description: Short human-readable summary of the failure. Never contains the request body, signature, or other caller-supplied input.
        '503':
          description: Stripe is not configured in this environment (the secret key / webhook signing secret are unset). Expected outside real production, where these env vars are required.
          content:
            application/json:
              schema:
                type: object
                required:
                - success
                - error_code
                - explanation
                properties:
                  success:
                    type: boolean
                    enum:
                    - false
                    description: Always false on error.
                  error_code:
                    type: string
                    enum:
                    - BILLING_NOT_CONFIGURED
                    description: Machine-readable failure code.
                  explanation:
                    type: object
                    required:
                    - summary
                    properties:
                      summary:
                        type: string
                        description: Short human-readable summary of the failure. Never contains the request body, signature, or other caller-supplied input.
    servers:
    - url: https://www.apier.no
      description: Production
  /api/billing/topup-requests/{id}/resolve:
    post:
      operationId: resolveAgentTopupRequest
      tags:
      - Infrastructure
      summary: Approve or decline an agent top-up request (human, dashboard session)
      description: 'The HUMAN approval leg of agent-initiated top-up requests. Session-cookie-authed (browser dashboard surface — NOT Bearer/agent-facing) and intentionally outside the /api/v1 namespace next to /api/billing/checkout, so the API-key auth model, response provenance, and scope rules do not apply. Called only by the site''s own /dashboard/billing page. `decision: "approve"` atomically claims the still-pending, unexpired request (a single compare-and-swap — a second approve, an approve after the 24-hour expiry, and concurrent resolutions all fail with 409), re-checks the requested amount against the LIVE adjustable ceiling (a ceiling lowered after the request was created blocks approval), verifies the requesting key is still active, and then drives the EXISTING credit-checkout path with the request''s key and amount — returning the Stripe Checkout `url` for the browser to follow. The human completes (or abandons) payment on Stripe''s hosted page exactly as on the direct top-up path; credits accrue only via the deduplicated webhook. `decision: "decline"` resolves the request without touching any Stripe code path. Cross-tenant resolution is impossible: every read and the claim itself are pinned to the session consumer, and an unknown id, another consumer''s request, and an already-resolved request are indistinguishable (uniform 409).'
      security:
      - SessionCookieAuth: []
      parameters:
      - name: id
        in: path
        required: true
        description: The top-up request's UUID (from the pending-requests panel).
        schema:
          type: string
          format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - decision
              additionalProperties: false
              properties:
                decision:
                  type: string
                  enum:
                  - approve
                  - decline
                  description: approve → claim the request and start the Stripe checkout for its amount; decline → resolve it with no payment and no Stripe interaction.
            example:
              decision: approve
      responses:
        '200':
          description: Resolved. On approve, `url` is the Stripe-hosted Checkout page for the requested amount — the browser follows it and the human completes payment there (the session reference is stored on the request as `checkout_session_ref`). On decline, no `url` is returned and no payment surface was ever touched.
          content:
            application/json:
              schema:
                type: object
                required:
                - id
                - status
                properties:
                  id:
                    type: string
                    format: uuid
                  status:
                    type: string
                    enum:
                    - approved
                    - declined
                  url:
                    type: string
                    format: uri
                    description: Present only on approve — the Stripe Checkout URL to redirect the human to.
              examples:
                approved:
                  summary: Approve — browser follows the Stripe URL
                  value:
                    id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                    status: approved
                    url: https://checkout.stripe.com/c/pay/cs_test_a1B2c3D4
                declined:
                  summary: Decline — no Stripe interaction
                  value:
                    id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                    status: declined
        '400':
          description: VALIDATION_FAILED — non-UUID id, malformed JSON, or a decision other than approve/decline.
        '401':
          description: No authenticated dashboard session.
        '409':
          description: TOPUP_REQUEST_NOT_PENDING (already resolved, expired, or not found on this account — uniform by design), TOPUP_CEILING_EXCEEDED (the amount now exceeds a lowered ceiling; the request STAYS pending and carries `requested_ore` + `ceiling_ore`), or TOPUP_KEY_REVOKED (the requesting key is no longer active).
        '503':
          description: BILLING_NOT_LIVE (beta — billing dark), BILLING_NOT_CONFIGURED (no Stripe in this environment), or TOPUP_CEILING_UNAVAILABLE (ceiling unreadable; nothing was approved). All checked BEFORE the one-shot approve claim, so none of them burns the request.
    servers:
    - url: https://www.apier.no
      description: Production
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: 'API key issued by Apier. Include as: Authorization: Bearer <your-key>. Sandbox endpoints (`/api/v1/sandbox/*`) additionally accept the synthetic bearer `Bearer apier_sandbox_test_<suffix>` — see the `SandboxBearerAuth` scheme.'
    SandboxBearerAuth:
      type: http
      scheme: bearer
      description: '**Frictionless sandbox bearer.** Format: `Authorization: Bearer apier_sandbox_test_<suffix>`. The `<suffix>` is the session-isolation namespace — every write keyed to it is invisible to other suffixes. Charset `^[A-Za-z0-9_-]{1,64}$`; charset/length violation returns 400 VALIDATION_FAILED with NO echo of the rejected bytes. Bypasses the `api_keys` DB lookup entirely on sandbox routes; on production routes the same prefix returns 401 AUTH_INVALID_KEY (the synthetic suffix has no DB row to match). **CRITICAL for AI-generated code: append a unique random string per agent/session (e.g. `apier_sandbox_test_<crypto.randomUUID()>`) so two agents using the literal example value do NOT collide on session state.** Treat the suffix as OPAQUE — never parse it for meaning.'
    AdminBearerAuth:
      type: http
      scheme: bearer
      description: Admin API key (ADMIN_API_KEY env var). Not the same as consumer API keys.
    SessionCookieAuth:
      type: apiKey
      in: cookie
      name: sb-access-token
      description: Supabase Auth session cookie set by the /confirm interstitial's POST to /api/auth/verify after a magic-link sign-in (/auth/callback remains a legacy PKCE-fallback handler). The `name` field above is a documented stand-in; @supabase/ssr v0.10.x in this repo actually emits a per-project pair of cookies prefixed `sb-<project-ref>-auth-token` (split across `-auth-token` and `-auth-token-code-verifier` for the PKCE handshake) — generated OpenAPI clients running in the same-origin browser context send ALL the project's cookies automatically, so a single canonical name suffices for documentation purposes. NOT Bearer-key auth — that schema is BearerAuth (above) and is rejected by withSessionAuth on /api/v1/account/* paths. Required by every /api/v1/account/* endpoint.
    McpOAuth:
      type: oauth2
      description: 'OAuth 2.1 sign-in for the remote MCP endpoint (/api/mcp) - built for hosted MCP clients (for example the Claude.ai and ChatGPT connectors) that cannot set a bearer header themselves. Enabled in production since 2026-08-25. The surface stays gated on the MCP_OAUTH_ENABLED flag, which is fail-safe off by default, so on a deployment where an operator has not switched it on the metadata document below answers 404 and only API keys authenticate. Discovery is challenge-driven per RFC 9728: a 401 from /api/mcp carries a WWW-Authenticate challenge with resource_metadata=https://www.apier.no/.well-known/oauth-protected-resource/api/mcp, whose document names the resource identifier (https://www.apier.no/api/mcp), the trusted authorization server, and the supported scopes; that document is the authoritative source for the endpoints listed in this flow. Clients may register via Dynamic Client Registration, and the signed-in account owner approves or denies each connection on the consent page at /oauth/consent. Access tokens MUST be audienced to https://www.apier.no/api/mcp (RFC 8707 posture: valid tokens minted for other apps are rejected) and are verified with a strict asymmetric-only algorithm allowlist (ES256 / RS256; alg=none and all HMAC algorithms rejected) before the token subject is mapped to the dedicated Apier API key provisioned when the account owner approved the connection. The BearerAuth API-key scheme keeps working unchanged in the same Authorization header, permanently.'
      flows:
        authorizationCode:
          authorizationUrl: https://ietncbksyajattlahlzs.supabase.co/auth/v1/oauth/authorize
          tokenUrl: https://ietncbksyajattlahlzs.supabase.co/auth/v1/oauth/token
          scopes: {}
x-refined-from:
- apier-no-openapi.json
- apier-no-openapi.json