{"openapi":"3.0.3","info":{"title":"AI Batteries Included — Headless API","version":"1.0.0","description":"Provision and manage AWS accounts with IAM, SSO, and GitHub OIDC access.\n\n## For AI Agents\n\nThis is an agent-first API. If you are an LLM or AI agent, see GET /v1/llms.txt for a plain-text guide optimized for programmatic consumption.\n\n## Quick Start\n\n1. **Sign up** — POST /stripe/setup with an email to get a Stripe Checkout URL. Complete payment.\n2. **Get API key** — After checkout, GET /stripe/session/{session_id} returns your API key (shown once).\n3. **Provision an account** — POST /accounts with Bearer auth. Optionally include githubRepos for OIDC deployment access.\n4. **Poll for completion** — GET /accounts/{id} until status is \"active\" (provisioning takes 1–3 minutes).\n5. **Deploy** — Use the oidcRoleArn from the account detail in your GitHub Actions workflows.\n\n## Common Workflows\n\n- **Add GitHub repos later**: PATCH /accounts/{id} with {\"githubRepos\": [\"org/repo\"]} to update OIDC trust policy.\n- **Multiple accounts**: POST /accounts again to provision additional AWS accounts under your customer.\n- **Rotate API keys**: POST /keys to create a new key, DELETE /keys/{id} to revoke old ones.\n\n## Authentication\n\nAll endpoints except /stripe/* require Bearer auth with your API key: `Authorization: Bearer <key>`.","contact":{"email":"support@aibatteriesincluded.com"}},"servers":[{"url":"https://api.aibatteriesincluded.com/v1","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key obtained after Stripe checkout."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]},"AccountSummary":{"type":"object","properties":{"accountId":{"type":"string","format":"uuid"},"awsAccountId":{"type":"string","example":"123456789012"},"status":{"type":"string","enum":["pending","creating","active","failed","suspended"]},"provisioningStep":{"type":"string","enum":["create_account","check_status","wait_for_role","move_to_ou","create_iam_user","setup_sso_access","setup_oidc","send_welcome_email","complete","failed"]},"createdAt":{"type":"string","format":"date-time"}}},"AccountDetail":{"type":"object","properties":{"accountId":{"type":"string","format":"uuid"},"awsAccountId":{"type":"string"},"status":{"type":"string"},"provisioningStep":{"type":"string"},"iamUserName":{"type":"string"},"signInUrl":{"type":"string","format":"uri"},"ssoUserName":{"type":"string"},"ssoPortalUrl":{"type":"string","format":"uri"},"githubRepos":{"type":"array","items":{"type":"string"},"example":["my-org/my-repo"]},"oidcRoleArn":{"type":"string","example":"arn:aws:iam::123456789012:role/GitHubActionsDeployRole"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"error":{"type":"string"}}},"ApiKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"keyPrefix":{"type":"string","example":"a4f9ab2b"},"name":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"lastUsedAt":{"type":"string","format":"date-time"},"revokedAt":{"type":"string","format":"date-time"}}},"ApiKeyCreated":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"key":{"type":"string","description":"Raw API key. Only returned once at creation time."},"keyPrefix":{"type":"string"},"name":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"ProvisioningEvent":{"type":"object","properties":{"accountId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"},"step":{"type":"string"},"status":{"type":"string","enum":["started","succeeded","failed"]},"detail":{"type":"string"},"error":{"type":"string"}}}}},"paths":{"/accounts":{"get":{"summary":"List accounts","description":"List all AWS accounts for the authenticated customer.","tags":["Accounts"],"responses":{"200":{"description":"Account list","content":{"application/json":{"schema":{"type":"object","properties":{"accounts":{"type":"array","items":{"$ref":"#/components/schemas/AccountSummary"}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Provision account","description":"Start provisioning a new AWS account. Optionally specify GitHub repos for OIDC deployment access.","tags":["Accounts"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"githubRepos":{"type":"array","items":{"type":"string"},"description":"GitHub repositories (org/repo format) to grant deployment access via OIDC.","example":["my-org/my-app","my-org/infra"]}}}}}},"responses":{"202":{"description":"Provisioning started","content":{"application/json":{"schema":{"type":"object","properties":{"accountId":{"type":"string","format":"uuid"},"status":{"type":"string","example":"pending"},"createdAt":{"type":"string","format":"date-time"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/accounts/{id}":{"get":{"summary":"Get account","description":"Get account details including credentials, SSO info, and OIDC role ARN when provisioning is complete.","tags":["Accounts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Account details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountDetail"}}}},"404":{"description":"Account not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Update account","description":"Update account settings. Currently supports updating GitHub repos for OIDC access. Re-runs OIDC setup to update the trust policy.","tags":["Accounts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"githubRepos":{"type":"array","items":{"type":"string"},"description":"Updated list of GitHub repositories (org/repo format)."}},"required":["githubRepos"]}}}},"responses":{"200":{"description":"Account updated","content":{"application/json":{"schema":{"type":"object","properties":{"accountId":{"type":"string"},"awsAccountId":{"type":"string"},"githubRepos":{"type":"array","items":{"type":"string"}},"oidcRoleArn":{"type":"string"},"status":{"type":"string"}}}}}},"404":{"description":"Account not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Account not active","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/keys":{"get":{"summary":"List API keys","description":"List all API keys for the authenticated customer.","tags":["API Keys"],"responses":{"200":{"description":"Key list","content":{"application/json":{"schema":{"type":"object","properties":{"keys":{"type":"array","items":{"$ref":"#/components/schemas/ApiKey"}}}}}}}}},"post":{"summary":"Create API key","description":"Create a new API key. The raw key is only returned once in the response.","tags":["API Keys"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Display name for the key."}},"required":["name"]}}}},"responses":{"201":{"description":"Key created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreated"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/keys/{id}":{"delete":{"summary":"Revoke API key","description":"Revoke an API key. The key will no longer be usable.","tags":["API Keys"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Key revoked"},"400":{"description":"Missing key ID","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/stripe/setup":{"post":{"summary":"Create Stripe checkout session","description":"Creates a Stripe Checkout session for new customer onboarding. No auth required.","tags":["Billing"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email","description":"Customer email address"}}}}}},"responses":{"200":{"description":"Checkout session created","content":{"application/json":{"schema":{"type":"object","properties":{"sessionId":{"type":"string"},"url":{"type":"string","format":"uri"}}}}}},"400":{"description":"Email is required","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}}}}},"/stripe/session/{id}":{"get":{"summary":"Retrieve API key after checkout","description":"After Stripe checkout completes, the front-end redirects to a success page with a session_id. Call this endpoint to retrieve the customer's API key. The key is returned once and then deleted.","tags":["Billing"],"security":[],"parameters":[{"name":"id","in":"path","required":true,"description":"Stripe Checkout Session ID (cs_...)","schema":{"type":"string"}}],"responses":{"200":{"description":"API key retrieved","content":{"application/json":{"schema":{"type":"object","properties":{"customerId":{"type":"string","format":"uuid"},"email":{"type":"string"},"apiKey":{"type":"string","description":"Raw API key. Save it now — it cannot be retrieved again."},"message":{"type":"string"}}}}}},"404":{"description":"Session not found or already retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/stripe/callback":{"post":{"summary":"Stripe webhook","description":"Receives Stripe webhook events. Not for direct use.","tags":["Billing"],"security":[],"responses":{"200":{"description":"Event processed"}}}},"/admin/accounts":{"get":{"summary":"List all accounts (admin)","description":"List all accounts across all customers. Requires admin API key.","tags":["Admin"],"responses":{"200":{"description":"All accounts","content":{"application/json":{"schema":{"type":"object","properties":{"accounts":{"type":"array","items":{"$ref":"#/components/schemas/AccountDetail"}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/admin/events":{"get":{"summary":"List provisioning events (admin)","description":"List provisioning events with optional filters.","tags":["Admin"],"parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["started","succeeded","failed"]}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Only return events after this timestamp."}],"responses":{"200":{"description":"Event list","content":{"application/json":{"schema":{"type":"object","properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/ProvisioningEvent"}}}}}}}}}},"/admin/accounts/{id}/suspend":{"post":{"summary":"Suspend account (admin)","description":"Suspend a customer account.","tags":["Admin"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Account suspended","content":{"application/json":{"schema":{"type":"object","properties":{"accountId":{"type":"string"},"status":{"type":"string","example":"suspended"},"provisioningStep":{"type":"string"},"updatedAt":{"type":"string","format":"date-time"}}}}}},"404":{"description":"Account not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}