{
  "openapi": "3.1.0",
  "info": {
    "title": "Recoup API - Accounts",
    "description": "API documentation for the Recoup platform - an AI agent platform for the music industry",
    "license": {
      "name": "MIT"
    },
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://api.recoupable.dev"
    }
  ],
  "paths": {
    "/api/organizations/professionals": {
      "get": {
        "operationId": "getOrganizationsProfessionals",
        "summary": "List professional roster",
        "description": "List organization-private songwriter/producer records. Names are discovery candidates, never identity proof. Follow next_cursor until null to inspect the complete roster. Membership is rechecked on every page; responses are private and not cached. Legacy MCP equivalent (API key or Privy token): list_professional_roster. Not exposed through delegated OAuth MCP.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "after",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "next_cursor returned by the previous page."
          }
        ],
        "responses": {
          "200": {
            "description": "Up to 100 professionals",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "professionals",
                    "next_cursor"
                  ],
                  "properties": {
                    "professionals": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/OrganizationProfessional"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid organization ID or cursor",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Organization access denied, revoked, or record outside this organization",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Unavailable storage or invalid response; retry the same page",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "postOrganizationsProfessionals",
        "summary": "Confirm professional roster addition",
        "description": "Requires explicit operator identity confirmation and organization roster intent. Use new only after confirming a distinct professional, including resolving same-name candidates; never infer identity from a name. Use existing with a professional_id from this organization to add roles without renaming. Both songwriter and producer can belong to one record. This operation creates no login account, shared canonical identity, catalog rights, enrichment job, or cross-workspace context. Research/name intake alone never calls this operation. Membership is rechecked before idempotency replay. Legacy MCP equivalent (API key or Privy token): confirm_professional_roster. Not exposed through delegated OAuth MCP. Returns the original saved response on retry, including its created flag and original status (201 for a new record, 200 for an existing record).",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "organization_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "idempotency_key": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Generate once per deliberate operation. Persist and reuse after a timeout or lost response. Scoped to the organization and actor. Different input with the same key is rejected."
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "new",
                      "existing"
                    ]
                  },
                  "name": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 200
                  },
                  "professional_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "roles": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 2,
                    "items": {
                      "type": "string",
                      "enum": [
                        "songwriter",
                        "producer"
                      ]
                    }
                  },
                  "confirmed": {
                    "type": "boolean",
                    "enum": [
                      true
                    ]
                  },
                  "roster_intent": {
                    "type": "string",
                    "enum": [
                      "add"
                    ]
                  }
                },
                "required": [
                  "organization_id",
                  "idempotency_key",
                  "mode",
                  "roles",
                  "confirmed",
                  "roster_intent"
                ],
                "oneOf": [
                  {
                    "properties": {
                      "mode": {
                        "enum": [
                          "new"
                        ]
                      }
                    },
                    "required": [
                      "name"
                    ],
                    "not": {
                      "required": [
                        "professional_id"
                      ]
                    }
                  },
                  {
                    "properties": {
                      "mode": {
                        "enum": [
                          "existing"
                        ]
                      }
                    },
                    "required": [
                      "professional_id"
                    ],
                    "not": {
                      "required": [
                        "name"
                      ]
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Existing professional roles saved, or replayed existing-record operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "professional",
                    "created"
                  ],
                  "properties": {
                    "professional": {
                      "$ref": "#/components/schemas/OrganizationProfessional"
                    },
                    "created": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "New professional saved, or replayed new-record operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "professional",
                    "created"
                  ],
                  "properties": {
                    "professional": {
                      "$ref": "#/components/schemas/OrganizationProfessional"
                    },
                    "created": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid or unconfirmed request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Organization access denied, revoked, or record outside this organization",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Request key already used for different input or actor",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Unavailable storage or unconfirmed response; retry with the same key and input",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/accounts/{id}": {
      "get": {
        "operationId": "getAccountsById",
        "description": "Retrieve detailed account information by ID. Returns the account with associated profile info, emails, and wallet addresses.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier (UUID) of the account",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Account retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetAccountResponse"
                }
              }
            }
          },
          "404": {
            "description": "Account not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/accounts/id": {
      "get": {
        "operationId": "getAccountsId",
        "description": "Retrieve the ID of the authenticated account associated with the provided credentials. This is useful when you have an API key or access token but do not yet know the corresponding accountId.",
        "parameters": [],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Account ID retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetAccountIdResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/accounts": {
      "post": {
        "operationId": "postAccounts",
        "description": "Create a new account or retrieve an existing account by email or wallet address. If an account with the provided email or wallet already exists, returns that account. Otherwise creates a new account and initializes credits.",
        "requestBody": {
          "description": "Account credentials to create or lookup",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAccountRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Account created or retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountDataResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - failed to create account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patchAccounts",
        "description": "Update an existing account's profile information including name, organization, image, instruction, job title, role type, company name, and knowledges. Requires authentication via x-api-key or Authorization Bearer token. The authenticated account may update itself or a permitted account_id override.",
        "requestBody": {
          "description": "Account fields to update",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAccountRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Account updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountDataResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - account not found or update failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - account override not permitted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/accounts/artists": {
      "post": {
        "operationId": "postAccountsArtists",
        "description": "Add an artist to an account's list of associated artists. If the artist is already associated with the account, returns success without modification.",
        "requestBody": {
          "description": "Account and artist identifiers",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddArtistToAccountRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Artist added to account successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AddArtistSuccessResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - account not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/organizations": {
      "get": {
        "operationId": "getOrganizations",
        "description": "Retrieve all organizations that the authenticated account belongs to. Pass account_id to retrieve organizations for a specific account the API key has access to.",
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "account_id",
            "in": "query",
            "description": "Filter to a specific account. Only applicable when the authenticated account has access to multiple accounts via organization membership.",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Organizations retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetOrganizationsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid query parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationsErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - account_id is not a member of the organization or account tried to filter by an account_id they don't have access to",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "postOrganizations",
        "description": "Create a new organization. The creator is automatically added as a member of the organization.",
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "description": "Organization creation parameters",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateOrganizationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Organization created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateOrganizationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - missing required parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationsErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/organizations/artists": {
      "post": {
        "operationId": "postOrganizationsArtists",
        "description": "Add an artist to an organization. This allows organization members to access and manage the artist. This endpoint is idempotent - calling it multiple times with the same artistId and organizationId will not create duplicate records.",
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "description": "Artist-organization association parameters",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddArtistToOrganizationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Artist added to organization successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AddArtistToOrganizationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - missing required parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationsErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationsErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Caller is not a member of the organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationsErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/organizations/members": {
      "post": {
        "operationId": "postOrganizationsMembers",
        "description": "Add a member to an organization. This endpoint is idempotent - Adding an existing member returns the existing membership.",
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "description": "Member-organization association parameters",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddOrganizationMemberRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Member added to organization successfully (or already a member)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AddOrganizationMemberResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid or missing parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - caller is not a member of the organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteOrganizationsMembers",
        "description": "Remove a member from an organization. This endpoint is idempotent - Removing an account that is not a member succeeds without error.",
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The account ID of the organization"
          },
          {
            "name": "account_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The account ID of the member to remove"
          }
        ],
        "responses": {
          "200": {
            "description": "Member removed from organization (or was not a member)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RemoveOrganizationMemberResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid or missing parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - caller is not a member of the organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/organizations/domains": {
      "get": {
        "operationId": "getOrganizationsDomains",
        "description": "List the email domains mapped to an organization. Accounts that sign up with an email at a mapped domain automatically join the organization.",
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The account ID of the organization"
          }
        ],
        "responses": {
          "200": {
            "description": "Domains retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetOrganizationDomainsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid or missing parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - caller is not a member of the organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "postOrganizationsDomains",
        "description": "Map an email domain to an organization for automatic membership. After mapping, any account that signs up (or signs in) with an email at this domain is automatically added to the organization. A domain can belong to at most one organization.  This endpoint is idempotent - re-adding the same domain to the same organization returns the existing mapping.",
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "description": "Domain-organization mapping parameters",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddOrganizationDomainRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Domain mapped to organization successfully (or already mapped)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AddOrganizationDomainResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid or missing parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - caller is not a member of the organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Conflict - domain is already mapped to a different organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteOrganizationsDomains",
        "description": "Remove an email domain mapping from an organization. New signups at this domain will no longer auto-join the organization; existing members are not affected. This endpoint is idempotent.",
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "organization_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The account ID of the organization"
          },
          {
            "name": "domain",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The email domain to unmap (e.g. \"seekermusic.com\")"
          }
        ],
        "responses": {
          "200": {
            "description": "Domain mapping removed (or did not exist)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RemoveOrganizationDomainResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid or missing parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - caller is not a member of the organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/subscriptions/sessions": {
      "post": {
        "operationId": "postSubscriptionsSessions",
        "description": "Create a checkout session to start a subscription for the authenticated account. Returns a hosted checkout URL that the client should redirect to. `plan` picks the price: `pro` (default) is pre-configured with a 30-day trial period; `starter` is charged at checkout with no trial.",
        "requestBody": {
          "description": "Session creation parameters",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSubscriptionSessionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Checkout session created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateSubscriptionSessionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - missing or invalid parameters, or `plan` is `starter` while the Starter price is not configured (`error` is literally `starter_unavailable`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionSessionErrorResponse"
                },
                "example": {
                  "error": "starter_unavailable"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - an auth header was supplied but is invalid (omit it entirely for an anonymous session)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionSessionErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionSessionErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/accounts/{id}/subscription": {
      "get": {
        "operationId": "getAccountsByIdSubscription",
        "description": "Retrieve the subscription that confers an account's plan, directly or via an organization: `isPro`, `status`, `plan`, `source`, plus the billing fields `name`, `amountCents`, `currency`, `interval`, `collectionMethod` and `currentPeriodEnd`. Everything but `isPro` and `status` is null when `status` is `none`. `id` may be the authenticated account or an organization the caller belongs to.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier (UUID) of the account. Must be the authenticated account or another accessible via organization membership.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Subscription retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionResponse"
                },
                "examples": {
                  "free": {
                    "summary": "No paid entitlement",
                    "value": {
                      "isPro": false,
                      "status": "none",
                      "plan": null,
                      "source": null,
                      "name": null,
                      "amountCents": null,
                      "currency": null,
                      "interval": null,
                      "collectionMethod": null,
                      "currentPeriodEnd": null
                    }
                  },
                  "starter": {
                    "summary": "Paid Starter, not Pro",
                    "value": {
                      "isPro": false,
                      "status": "active",
                      "plan": "starter",
                      "source": "account",
                      "name": null,
                      "amountCents": null,
                      "currency": null,
                      "interval": null,
                      "collectionMethod": null,
                      "currentPeriodEnd": null
                    }
                  },
                  "directPro": {
                    "summary": "Direct Pro",
                    "value": {
                      "isPro": true,
                      "status": "active",
                      "plan": "pro",
                      "source": "account",
                      "name": null,
                      "amountCents": null,
                      "currency": null,
                      "interval": null,
                      "collectionMethod": null,
                      "currentPeriodEnd": null
                    }
                  },
                  "organizationPro": {
                    "summary": "Organization Pro overrides account Starter",
                    "value": {
                      "isPro": true,
                      "status": "active",
                      "plan": "pro",
                      "source": "organization",
                      "name": null,
                      "amountCents": null,
                      "currency": null,
                      "interval": null,
                      "collectionMethod": null,
                      "currentPeriodEnd": null
                    }
                  },
                  "inactive": {
                    "summary": "Canceled subscription: current entitlement is none",
                    "value": {
                      "isPro": false,
                      "status": "none",
                      "plan": null,
                      "source": null,
                      "name": null,
                      "amountCents": null,
                      "currency": null,
                      "interval": null,
                      "collectionMethod": null,
                      "currentPeriodEnd": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionErrorResponse"
                },
                "example": {
                  "error": "Unauthorized"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - account not accessible to the authenticated account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Account not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/accounts/{id}/credits": {
      "get": {
        "operationId": "getAccountsByIdCredits",
        "description": "Retrieve the current credit balance for an account. Returns the remaining credits along with the plan-derived monthly total and used count, plus a flag indicating whether the account is on a pro plan (directly or via an organization). Credits refill monthly; the `timestamp` field reflects the last refill or balance update.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier (UUID) of the account. Must be the authenticated account or another accessible via organization membership.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Credit balance retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountCreditsResponse"
                },
                "examples": {
                  "free": {
                    "summary": "Free with an unavailable balance timestamp",
                    "value": {
                      "account_id": "11111111-1111-4111-8111-111111111111",
                      "remaining_credits": 3330000,
                      "total_credits": 3330000,
                      "used_credits": 0,
                      "is_pro": false,
                      "plan": "free",
                      "task_limit": 1,
                      "min_cadence_minutes": 10080,
                      "timestamp": null
                    }
                  },
                  "starter": {
                    "summary": "Paid Starter: is_pro remains false",
                    "value": {
                      "account_id": "11111111-1111-4111-8111-111111111111",
                      "remaining_credits": 15000000,
                      "total_credits": 20000000,
                      "used_credits": 5000000,
                      "is_pro": false,
                      "plan": "starter",
                      "task_limit": 3,
                      "min_cadence_minutes": 1440,
                      "timestamp": "2026-10-01T12:00:00Z"
                    }
                  },
                  "directPro": {
                    "summary": "Direct Pro",
                    "value": {
                      "account_id": "11111111-1111-4111-8111-111111111111",
                      "remaining_credits": 292450000,
                      "total_credits": 300000000,
                      "used_credits": 7550000,
                      "is_pro": true,
                      "plan": "pro",
                      "task_limit": null,
                      "min_cadence_minutes": 60,
                      "timestamp": "2026-10-01T12:00:00Z"
                    }
                  },
                  "organizationPro": {
                    "summary": "Effective Pro through an organization",
                    "value": {
                      "account_id": "11111111-1111-4111-8111-111111111111",
                      "remaining_credits": 292450000,
                      "total_credits": 300000000,
                      "used_credits": 7550000,
                      "is_pro": true,
                      "plan": "pro",
                      "task_limit": null,
                      "min_cadence_minutes": 60,
                      "timestamp": "2026-10-01T12:00:00Z"
                    }
                  },
                  "aboveAllotment": {
                    "summary": "Extra credits above the allowance: used_credits is zero",
                    "value": {
                      "account_id": "11111111-1111-4111-8111-111111111111",
                      "remaining_credits": 325000000,
                      "total_credits": 300000000,
                      "used_credits": 0,
                      "is_pro": true,
                      "plan": "pro",
                      "task_limit": null,
                      "min_cadence_minutes": 60,
                      "timestamp": "2026-10-01T12:00:00Z"
                    }
                  },
                  "negativeBalance": {
                    "summary": "Signed balance: usage display can exceed the allowance",
                    "value": {
                      "account_id": "11111111-1111-4111-8111-111111111111",
                      "remaining_credits": -1000,
                      "total_credits": 3330000,
                      "used_credits": 3331000,
                      "is_pro": false,
                      "plan": "free",
                      "task_limit": 1,
                      "min_cadence_minutes": 10080,
                      "timestamp": "2026-10-01T12:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountCreditsErrorResponse"
                },
                "example": {
                  "error": "Unauthorized"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - account not accessible to the authenticated account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountCreditsErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/accounts/{id}/usage": {
      "get": {
        "operationId": "getAccountsByIdUsage",
        "description": "List the charges that consumed an account's credits: one line item per deduction from `usage_events`, newest first, over a period. Each item carries the amount as the raw ledger integer (`credits_deducted`, micro-dollars: 1,000,000 = $1.00) and the same amount formatted as a dollar string (`usd`), and the response carries the total for the whole period, not just the page. Access is the same as [`GET /api/accounts/{id}/credits`](/api-reference/accounts/credits-get): the authenticated account itself, or another account reachable through organization membership.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The unique identifier (UUID) of the account. Must be the authenticated account or another accessible via organization membership.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of line items to return per page.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Both orders are descending: created_at uses timestamp then row ID; cost uses credits_deducted then row ID. Cost ties are ordered by ID, not timestamp.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "cost"
              ],
              "default": "created_at"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque paging token: pass next_cursor unchanged with the same sort, from and to. New time cursors retain both the last timestamp and row ID, so tied timestamps are not skipped. Cost cursors retain amount and row ID. Legacy timestamp-only cursors remain accepted as strict time boundaries; start a fresh traversal to obtain complete tie coverage.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Start of the period (inclusive), ISO 8601. Defaults to the start of the current UTC month.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "End of the period (exclusive), ISO 8601. Defaults to now.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Usage line items retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountUsageResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request: invalid query parameter, limit above 100, malformed cursor, or a non-positive period after database timestamp normalization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountCreditsErrorResponse"
                },
                "example": {
                  "error": "limit must be between 1 and 100"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountCreditsErrorResponse"
                },
                "example": {
                  "error": "Unauthorized"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - account not accessible to the authenticated account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountCreditsErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/accounts/{id}/payment-method": {
      "get": {
        "operationId": "getAccountsByIdPaymentMethod",
        "description": "Retrieve the default payment method on file for an account. An account may be tagged on more than one Stripe customer (for example an organization whose card was saved on one customer and whose invoiced plan lives on another); the card is read from the tagged customer that holds a default payment method. Returns `card: null` when the selected customer has no supported default card, including when no tagged customer exists — the top-up dialog uses this to decide whether to show a pre-charge confirmation (card present) or route to a checkout session to collect one (`card: null`). Cards are returned even when expired; callers should compare `exp_month` / `exp_year` against the current date and warn the customer, since an off-session charge against an expired card will decline. Removing the selected card does not remove other saved cards: a later read can select a different remaining card. Auto top-up stays off after successful removal until explicitly re-enabled.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier (UUID) of the account. Must be the authenticated account or another accessible via organization membership.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Default payment method retrieved successfully (may be `null` if none on file).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountPaymentMethodResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountPaymentMethodErrorResponse"
                },
                "example": {
                  "error": "Unauthorized"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - the account is not the caller's and not an organization they belong to (an unknown id also returns 403, never 404)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountPaymentMethodErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "postAccountsByIdPaymentMethod",
        "description": "Create a $0 card-on-file checkout session for an account. Stripe `setup` mode saves a payment method without charging anything or starting a subscription; the saved card becomes the account's default and is what credit purchases and auto top-up charge. The card is saved on the account's Stripe customer that already holds a default card, or the newest tagged customer; a customer is created (and tagged with the account id) if none exists yet. Returns a hosted checkout URL that the client should redirect to. `id` may be the authenticated account or an organization the caller belongs to.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier (UUID) of the account. Must be the authenticated account or another accessible via organization membership.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "description": "Card-on-file session parameters",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCardOnFileSessionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Card-on-file session created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateSubscriptionSessionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - missing or invalid parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountPaymentMethodErrorResponse"
                },
                "example": {
                  "error": "successUrl must be a valid URL"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountPaymentMethodErrorResponse"
                },
                "example": {
                  "error": "Unauthorized"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - the account is not the caller's and not an organization they belong to (an unknown id also returns 403, never 404)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountPaymentMethodErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountPaymentMethodErrorResponse"
                },
                "example": {
                  "error": "Internal server error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteAccountsByIdPaymentMethod",
        "description": "Turn off automatic credit top-ups for the authorized account, then detach its selected default card. This removes one card selected from the account's tagged Stripe customers; it does not delete every saved card. A successful request returns 204 with no response body. `id` may be the authenticated account or an organization the caller belongs to.\n\nOther cards remain attached. A later `GET /api/accounts/{id}/payment-method` can return another remaining card; removal does not guarantee `card: null` or checkout-only purchases. A later explicitly requested credit purchase can use a remaining card, while an account with no card uses checkout. Removal does not turn automatic top-ups back on; enabling them again requires an explicit settings update.\n\nThe API saves `auto_topup_enabled: false` before detaching the selected card. If saving that setting fails, no card is detached. If settings are saved but detachment fails, automatic top-ups remain off and the request returns 500. Both failures return the same generic error, so read the payment method and auto-top-up settings to determine the current state. A missing customer or selected card returns 404 without changing settings or cards.\n\nAfter an error or uncertain response, reread both states before deciding whether to retry. A successful removal may expose another selected card, so blindly repeating DELETE can remove a different card. Removal preserves balances, configured top-up amounts and thresholds, and other saved cards. It does not cancel subscriptions, invoices, a charge already in progress, or a concurrent explicit settings update.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier (UUID) of the account. Must be the authenticated account or another accessible via organization membership.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Automatic top-ups are off and the selected card is detached; no response body."
          },
          "400": {
            "description": "Invalid account id; no billing changes are performed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountPaymentMethodErrorResponse"
                },
                "example": {
                  "error": "id must be a valid UUID"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountPaymentMethodErrorResponse"
                },
                "example": {
                  "error": "Unauthorized"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - the account is not the caller's and not an organization they belong to (an unknown id also returns 403, never 404)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountPaymentMethodErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "No tagged Stripe customer or selected card exists. Settings and cards are unchanged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountPaymentMethodErrorResponse"
                },
                "example": {
                  "error": "No payment method on file"
                }
              }
            }
          },
          "500": {
            "description": "Unable to complete card removal. Automatic top-ups may already be off; read the card and settings before retrying.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountPaymentMethodErrorResponse"
                },
                "example": {
                  "error": "Internal server error"
                }
              }
            }
          }
        }
      }
    },
    "/api/accounts/{id}/portal": {
      "post": {
        "operationId": "postAccountsByIdPortal",
        "description": "Create a Stripe Customer Portal session for an account. Returns a hosted URL where the customer can update the card on file, view invoices, or cancel a Starter or Pro subscription; the client should redirect the user to that URL. The portal opens on the Stripe customer that owns the account's active subscription, so accounts without an active subscription get a 400 even when a tagged customer with a card exists. `id` may be the authenticated account or an organization the caller belongs to. Enterprise (invoiced) plans are managed with your Recoup contact and the app does not offer this portal for them, but the endpoint works for any account with an active subscription.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier (UUID) of the account. Must be the authenticated account or another accessible via organization membership.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "description": "Portal session parameters",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSubscriptionPortalRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Portal session created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateSubscriptionPortalResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid parameters, or the account has no active subscription",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionPortalErrorResponse"
                },
                "example": {
                  "error": "No active subscription found"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionPortalErrorResponse"
                },
                "example": {
                  "error": "Unauthorized"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - the account is not the caller's and not an organization they belong to (an unknown id also returns 403, never 404)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionPortalErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/accounts/{id}/payments": {
      "get": {
        "operationId": "getAccountsByIdPayments",
        "description": "List the invoices paid or owed by an account, newest first: subscription renewals, credit purchases, and invoiced enterprise plans alike. Invoices are merged across every Stripe customer tagged with the account id, so a card saved on one customer and an invoiced plan on another appear in one list. Non-draft rows carry the hosted invoice URL for the receipt; `url` is null for drafts. Returns an empty list (not 404) when the account has no tagged Stripe customer or no invoices yet. `startingAfter` is an invoice id from a previous page; the next page holds invoices created before it. `id` may be the authenticated account or an organization the caller belongs to.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier (UUID) of the account. Must be the authenticated account or another accessible via organization membership.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum rows to return.",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "startingAfter",
            "in": "query",
            "description": "Cursor for the next page: the `id` of the last payment from the previous response.",
            "required": false,
            "schema": {
              "type": "string"
            },
            "example": "in_1U5xj400JObOnOb5BE0CmxCt"
          }
        ],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Payments retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountPaymentsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid `id`, `limit`, or `startingAfter`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountPaymentsErrorResponse"
                },
                "example": {
                  "error": "limit must be between 1 and 100"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountPaymentsErrorResponse"
                },
                "example": {
                  "error": "Unauthorized"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - the account is not the caller's and not an organization they belong to (an unknown id also returns 403, never 404)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountPaymentsErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/accounts/{id}/auto-top-up": {
      "get": {
        "operationId": "getAccountsByIdAutoTopUp",
        "description": "Read the auto top-up settings for an account. Auto top-up is opt-in: it is off for every account until the account turns it on and chooses both the amount to buy and the balance that triggers it. When it is on, the api charges the default card on file for `amountCents` the first time a credit deduction leaves the balance below `thresholdCents`, then grants the credits and emails a receipt. `id` may be the authenticated account or an organization the caller belongs to.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier (UUID) of the account. Must be the authenticated account or another accessible via organization membership.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Auto top-up settings (defaults when never configured).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutoTopUpResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutoTopUpErrorResponse"
                },
                "example": {
                  "error": "Unauthorized"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - the account is not the caller's and not an organization they belong to (an unknown id also returns 403, never 404)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutoTopUpErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "putAccountsByIdAutoTopUp",
        "description": "Set the auto top-up settings for an account. All three fields are required on every call; there is no partial update. Turning it on requires a card on file (`GET /api/accounts/{id}/payment-method` returns a card), an amount between 5.00 and 1,000.00 USD, and a threshold below the amount. Turning it off keeps the last amount and threshold so the account can turn it back on without retyping them. Guardrails that apply once it is on: at most one top-up per account per 10 minutes; a card decline turns `enabled` back to `false`, records `lastError`, and emails the account instead of retrying; a successful selected-card removal turns it off before detachment, even when other saved cards remain. Removal does not cancel a charge already in progress. `id` may be the authenticated account or an organization the caller belongs to.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier (UUID) of the account. Must be the authenticated account or another accessible via organization membership.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "description": "Auto top-up settings",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAutoTopUpRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Settings saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutoTopUpResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid body, `enabled: true` without a card on file, `amountCents` outside 500..100000, `thresholdCents` negative, or `thresholdCents` not below `amountCents`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutoTopUpErrorResponse"
                },
                "example": {
                  "error": "Add a payment method before turning on auto top-up"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutoTopUpErrorResponse"
                },
                "example": {
                  "error": "Unauthorized"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - the account is not the caller's and not an organization they belong to (an unknown id also returns 403, never 404)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutoTopUpErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The account has no credits row and one could not be created for it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutoTopUpErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/credits/sessions": {
      "post": {
        "operationId": "postCreditsSessions",
        "description": "Top up credits on the authenticated account.\n\n**Credits are integer micro-dollars (1,000,000 = \\$1.00, the same 6-decimal unit as USDC).** The customer is charged the USD value of `credits` plus a Stripe processing fee (US card pricing: 2.9% + \\$0.30) — e.g. `credits: 100000000` charges \\$103.30 total (\\$100.00 credits + \\$3.30 fee).\n\n**Two outcomes, distinguished by response shape:**\n\n- **Auto-charged** — if the account has a card on file (from a prior subscription or top-up), the card is charged immediately and the response is `{ paymentIntentId, creditsPurchased, totalCents }`. Credits land in the account's balance asynchronously via Stripe webhook (typically within seconds). No human interaction required.\n\n- **Checkout required** — if no card is on file, or the saved card requires 3-D Secure authentication, the response is `{ id, url }` with a hosted Stripe Checkout URL. Redirect to that URL; credits land on successful payment.\n\nClients should discriminate on the presence of `url` (Checkout) vs `paymentIntentId` (auto-charged). Cards entered through the Checkout fallback are saved for future top-ups, so a customer's second top-up typically auto-charges.",
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "description": "Top-up parameters",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCreditsSessionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Top-up initiated successfully. Some fields are conditional on which path was taken — see each field's description.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditsTopupResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - missing or invalid parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditsSessionErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditsSessionErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/subscriptions/claim": {
      "post": {
        "operationId": "postSubscriptionsClaim",
        "description": "Attach a subscription bought through [Create Subscription Session](/api-reference/subscriptions/sessions-create) (anonymous path) to the authenticated account. Needed only when the signed-in email differs from the email typed into Stripe Checkout; when they match, the webhook already linked the subscription and this call is a no-op that returns 200.",
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "description": "The Checkout session to claim",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClaimSubscriptionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Subscription attached to the authenticated account (or already was)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClaimSubscriptionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - missing `session_id`, or the session has no subscription",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClaimSubscriptionErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClaimSubscriptionErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown Checkout session",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClaimSubscriptionErrorResponse"
                },
                "example": {
                  "status": "error",
                  "error": "session_not_found"
                }
              }
            }
          },
          "409": {
            "description": "The subscription belongs to another account that has signed in",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClaimSubscriptionErrorResponse"
                },
                "example": {
                  "status": "error",
                  "error": "already_claimed"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClaimSubscriptionErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/pulses": {
      "get": {
        "operationId": "getPulses",
        "description": "Retrieve pulse information for the authenticated account. If the account has access to organizations, pass account_id to filter to a specific account within those organizations.",
        "parameters": [
          {
            "name": "account_id",
            "in": "query",
            "description": "Filter to a specific account. Only applicable when the authenticated account has access to multiple accounts via organization membership.",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "active",
            "in": "query",
            "description": "Filter by active status. Set to 'true' to return only active pulses, 'false' for inactive pulses. If not provided, returns all pulses regardless of active status.",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Pulses retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PulsesResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid query parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - account_id is not a member of the organization or account tried to filter by an account_id they don't have access to",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patchPulses",
        "description": "Update the pulse settings for an account. Use this to enable or disable the pulse. Returns an array of pulses for consistency with the GET endpoint.",
        "requestBody": {
          "description": "Pulse fields to update",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdatePulseRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Pulse updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PulsesResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/emails": {
      "post": {
        "operationId": "postEmails",
        "description": "Send an email to one or more recipients. Emails are sent from `Agent by Recoup <agent@recoupable.dev>`.",
        "requestBody": {
          "description": "Email payload",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendEmailRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Email sent successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Email delivery failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/admins": {
      "get": {
        "operationId": "getAdmins",
        "description": "Check if the authenticated account is a Recoup admin. An account is considered an admin if it is a member of the Recoup organization. No input parameters required — authentication is performed via the x-api-key or Authorization header.",
        "parameters": [],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Admin status retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckAdminResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admins/sandboxes": {
      "get": {
        "operationId": "getAdminsSandboxes",
        "description": "Returns a list of all accounts and their sandbox usage statistics. Each item includes the account email, total number of sandboxes created, and the timestamp of the most recently created sandbox. Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token.",
        "parameters": [],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Account sandbox statistics retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminSandboxesResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - authenticated account is not a Recoup admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admins/sandboxes/orgs": {
      "get": {
        "operationId": "getAdminsSandboxesOrgs",
        "description": "Returns commit statistics for each repository in the recoupable GitHub organization. Each item includes the repo name, URL, total commit count, latest 5 commit messages, earliest and latest commit timestamps, and the list of account repo URLs that include this org repo as a submodule. Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token.",
        "parameters": [],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Org repo statistics retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminSandboxOrgsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - authenticated account is not a Recoup admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admins/emails": {
      "get": {
        "operationId": "getAdminsEmails",
        "description": "Returns Resend emails including HTML content. Provide either account_id (returns all emails for an account) or email_id (returns a single email by Resend ID). Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token. Email response shape matches the [Resend Retrieve Email API](https://resend.com/docs/api-reference/emails/retrieve-email).",
        "parameters": [
          {
            "name": "account_id",
            "in": "query",
            "description": "The account ID to fetch all emails for. Required if email_id is not provided.",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "email_id",
            "in": "query",
            "description": "A Resend email ID to fetch a single email. Required if account_id is not provided.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Emails retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminEmailsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - must provide either account_id or email_id",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - authenticated account is not a Recoup admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admins/coding/slack": {
      "get": {
        "operationId": "getAdminsCodingSlack",
        "description": "Returns a list of Slack mentions of the Recoup Coding Agent bot, pulled directly from the Slack API as the source of truth. Each entry includes the tagger's information, the prompt they sent, the timestamp, the channel, and any GitHub pull request URLs opened in response. Also returns aggregate pull request statistics. Supports optional time-period filtering. Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token. Optional tag filters by the exact, case-sensitive Slack author ID after trimming whitespace. Filtering happens after the existing period collection and before all totals are calculated; omission preserves the unfiltered report, and an unknown ID returns empty tags with zero totals. Empty or whitespace-only tag values return 400 after admin authentication. This is display filtering, not authorization or a reduction in Slack collection work. Collection retains its existing channel access, retention, history/thread pagination and partial-failure limits. No automatic caller, UI, polling, scheduled action or Slack send is added.",
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "description": "Time period to filter tags. One of: all (no date filter), daily (last 24 hours), weekly (last 7 days), monthly (last 30 days). Defaults to all.",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "daily",
                "weekly",
                "monthly"
              ],
              "default": "all"
            }
          },
          {
            "name": "tag",
            "in": "query",
            "description": "Optional exact, case-sensitive Slack author ID. Leading/trailing whitespace is trimmed; blank values are rejected. This filters already collected mentions before the totals are computed and does not change access or collection work.",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "pattern": "\\S"
            },
            "example": "U2"
          }
        ],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Slack tag analytics retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "total",
                    "total_pull_requests",
                    "tags_with_pull_requests",
                    "tags"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "success"
                      ],
                      "description": "Status of the request"
                    },
                    "total": {
                      "type": "integer",
                      "description": "Number of collected Coding Agent mentions after the requested period and optional author filter.",
                      "example": 134
                    },
                    "total_pull_requests": {
                      "type": "integer",
                      "description": "Number of pull request links across the filtered collected mentions.",
                      "example": 121
                    },
                    "tags_with_pull_requests": {
                      "type": "integer",
                      "description": "Number of filtered collected mentions with at least one pull request link.",
                      "example": 84
                    },
                    "tags": {
                      "type": "array",
                      "description": "List of Slack tag events",
                      "items": {
                        "type": "object",
                        "required": [
                          "user_id",
                          "user_name",
                          "prompt",
                          "timestamp",
                          "channel_id",
                          "channel_name"
                        ],
                        "properties": {
                          "user_id": {
                            "type": "string",
                            "description": "Slack ID of the person who tagged the agent",
                            "example": "U012AB3CD"
                          },
                          "user_name": {
                            "type": "string",
                            "description": "Display name of the person who tagged the agent",
                            "example": "Jane Smith"
                          },
                          "user_avatar": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "URL of the Slack avatar",
                            "example": "https://avatars.slack-edge.com/..."
                          },
                          "prompt": {
                            "type": "string",
                            "description": "The text of the message sent to the agent",
                            "example": "add dark mode support to the settings page"
                          },
                          "timestamp": {
                            "type": "string",
                            "format": "date-time",
                            "description": "ISO 8601 timestamp of the tag event",
                            "example": "2024-01-15T10:30:00.000Z"
                          },
                          "channel_id": {
                            "type": "string",
                            "description": "Slack channel ID where the tag occurred",
                            "example": "C012AB3CD"
                          },
                          "channel_name": {
                            "type": "string",
                            "description": "Human-readable name of the Slack channel",
                            "example": "dev-team"
                          },
                          "pull_requests": {
                            "type": "array",
                            "description": "GitHub pull request URLs opened by the Coding Agent in response to this prompt, parsed from bot replies in the Slack thread",
                            "items": {
                              "type": "string",
                              "format": "uri",
                              "example": "https://github.com/recoupable/api/pull/42"
                            },
                            "example": [
                              "https://github.com/recoupable/api/pull/42"
                            ]
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid period or empty/whitespace-only tag; validation follows admin authentication and stops before Slack collection.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminCodingSlackQueryError"
                }
              }
            }
          },
          "401": {
            "description": "Missing, conflicting or invalid credentials; inspect error or message according to the returned authentication envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminCodingSlackAuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - authenticated account is not a Recoup admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admins/content/slack": {
      "get": {
        "operationId": "getAdminsContentSlack",
        "description": "Returns a list of Slack mentions of the Recoup Content Agent bot, pulled directly from the Slack API as the source of truth. Each entry includes the tagger's information, the prompt they sent, the timestamp, the channel, and any video link responses. Also returns aggregate video statistics for measuring tag-to-video conversion. Supports optional time-period filtering. Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token.",
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "description": "Time period to filter tags. One of: all (no date filter), daily (last 24 hours), weekly (last 7 days), monthly (last 30 days). Defaults to all.",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "daily",
                "weekly",
                "monthly"
              ],
              "default": "all"
            }
          }
        ],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Slack tag analytics retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "total",
                    "total_videos",
                    "tags_with_videos",
                    "tags"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "success"
                      ],
                      "description": "Status of the request"
                    },
                    "total": {
                      "type": "integer",
                      "description": "Total number of times the Content Agent was tagged in the requested period",
                      "example": 18
                    },
                    "total_videos": {
                      "type": "integer",
                      "description": "Total number of videos generated by the Content Agent across all tags in the requested period",
                      "example": 12
                    },
                    "tags_with_videos": {
                      "type": "integer",
                      "description": "Number of tags that resulted in at least one video being generated",
                      "example": 10
                    },
                    "tags": {
                      "type": "array",
                      "description": "List of Slack tag events",
                      "items": {
                        "type": "object",
                        "required": [
                          "user_id",
                          "user_name",
                          "prompt",
                          "timestamp",
                          "channel_id",
                          "channel_name"
                        ],
                        "properties": {
                          "user_id": {
                            "type": "string",
                            "description": "Slack ID of the person who tagged the agent",
                            "example": "U012AB3CD"
                          },
                          "user_name": {
                            "type": "string",
                            "description": "Display name of the person who tagged the agent",
                            "example": "Jane Smith"
                          },
                          "user_avatar": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "URL of the Slack avatar",
                            "example": "https://avatars.slack-edge.com/..."
                          },
                          "prompt": {
                            "type": "string",
                            "description": "The text of the message sent to the agent",
                            "example": "create a highlight reel for the new single release"
                          },
                          "timestamp": {
                            "type": "string",
                            "format": "date-time",
                            "description": "ISO 8601 timestamp of the tag event",
                            "example": "2024-01-15T10:30:00.000Z"
                          },
                          "channel_id": {
                            "type": "string",
                            "description": "Slack channel ID where the tag occurred",
                            "example": "C012AB3CD"
                          },
                          "channel_name": {
                            "type": "string",
                            "description": "Human-readable name of the Slack channel",
                            "example": "content-team"
                          },
                          "video_links": {
                            "type": "array",
                            "description": "Video URLs generated by the Content Agent in response to this prompt, parsed from bot replies in the Slack thread",
                            "items": {
                              "type": "string",
                              "format": "uri",
                              "example": "https://recoupable.com/v/abc123"
                            },
                            "example": [
                              "https://recoupable.com/v/abc123"
                            ]
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - authenticated account is not a Recoup admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admins/coding/pr": {
      "get": {
        "operationId": "getAdminsCodingPr",
        "description": "Returns the status (open, closed, or merged) for each provided GitHub pull request URL. Accepts one or more `pull_requests` query parameters containing GitHub PR URLs. Uses the GitHub REST API to check each pull request's state. Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token.",
        "parameters": [
          {
            "name": "pull_requests",
            "in": "query",
            "description": "One or more GitHub pull request URLs to check. Repeat this parameter for each URL. Example: ?pull_requests=https://github.com/org/repo/pull/1&pull_requests=https://github.com/org/repo/pull/2",
            "required": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "format": "uri"
              },
              "minItems": 1,
              "maxItems": 50
            },
            "style": "form",
            "explode": true
          }
        ],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "PR merged status retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "pull_requests"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "success"
                      ],
                      "description": "Status of the request"
                    },
                    "pull_requests": {
                      "type": "array",
                      "description": "Status for each provided pull request URL",
                      "items": {
                        "type": "object",
                        "required": [
                          "url",
                          "status"
                        ],
                        "properties": {
                          "url": {
                            "type": "string",
                            "format": "uri",
                            "description": "The GitHub pull request URL",
                            "example": "https://github.com/recoupable/api/pull/42"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "open",
                              "closed",
                              "merged"
                            ],
                            "description": "The current status of the pull request",
                            "example": "merged"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request - missing or invalid pull_requests parameter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - authenticated account is not a Recoup admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admins/privy": {
      "get": {
        "operationId": "getAdminsPrivy",
        "description": "Returns Privy login statistics for a given time period. Results include counts for new accounts (created_at), active accounts (latest_verified_at), total Privy accounts across all time, and the full, unmodified Privy account objects. See [Privy User object documentation](https://docs.privy.io/api-reference/users/get-all) for the complete type definition. Defaults to period=all (no date filter). Requires the authenticated account to be a Recoup admin. Authentication via x-api-key or Authorization Bearer token.",
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "description": "Time period to filter logins. One of: all (no date filter), daily (last 24 hours), weekly (last 7 days), monthly (last 30 days). Defaults to all.",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "daily",
                "weekly",
                "monthly"
              ],
              "default": "all"
            }
          }
        ],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Privy login statistics retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "total",
                    "total_new",
                    "total_active",
                    "logins"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "success"
                      ],
                      "description": "Status of the request"
                    },
                    "total": {
                      "type": "integer",
                      "description": "Total number of accounts in Privy across all time (not filtered by period)",
                      "example": 42
                    },
                    "total_new": {
                      "type": "integer",
                      "description": "Number of accounts created (created_at) within the requested period",
                      "example": 15
                    },
                    "total_active": {
                      "type": "integer",
                      "description": "Total number of accounts matching either new or active criteria in the requested period",
                      "example": 30
                    },
                    "logins": {
                      "type": "array",
                      "description": "Full, unmodified Privy account objects. See [Privy User object docs](https://docs.privy.io/api-reference/users/get-all) for the complete type definition.",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - authenticated account is not a Recoup admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admins/artists/pro": {
      "get": {
        "operationId": "getAdminsArtistsPro",
        "description": "Retrieve the deduplicated list of artist IDs owned by pro accounts. An account is \"pro\" when its email belongs to an enterprise domain or it has an active Stripe subscription. Admin-scoped: requires an admin-flagged API key because the response identifies paying customer accounts.",
        "security": [
          {
            "apiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Pro artist IDs retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ArtistsProResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid authentication"
          },
          "403": {
            "description": "Forbidden - caller is authenticated but not admin-scoped"
          },
          "500": {
            "description": "Internal server error while fetching pro artists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ArtistsProResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admins/credits": {
      "post": {
        "operationId": "postAdminsCredits",
        "description": "Sets an account's credit balance, and records who set it and why. Requires the authenticated account to be a Recoup admin.\n\n**Absolute, not a delta.** `remaining_credits` is the balance the account is left holding, whatever it held before — the outcome never depends on the balance at the moment the request lands. The prior balance comes back as `previous_credits` for the record. There is deliberately no add/subtract variant.\n\n**Every grant is audited.** `reason` is required and must be non-empty. The grant is stored against the acting admin's account ID and is readable afterwards in the `grants` array of [`GET /api/admins/credits/events`](/api-reference/admins/credits-events).\n\n**A grant is never reduced by the monthly refill.** Credit balances are topped up to the plan total by a monthly refill that runs lazily on the next read of [`GET /api/accounts/{id}/credits`](/api-reference/accounts/credits-get), once the underlying row is more than a month old. That refill is a floor, not an assignment: it raises a balance up to the plan total and never lowers one. A grant above the plan total therefore survives every refill and holds until it is spent, so headroom granted once stays granted and does not need re-granting on a schedule.",
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "description": "The account to set, the balance to leave it at, and why",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminGrantCreditsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Balance set and the grant recorded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminGrantCreditsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body, or a missing/invalid `account_id`, `remaining_credits`, or `reason`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminGrantCreditsValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - authenticated account is not a Recoup admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "No account exists with the supplied `account_id`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error while setting the balance or recording the grant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admins/credits/rollup": {
      "get": {
        "operationId": "getAdminsCreditsRollup",
        "description": "Returns the per-account rollup of credit usage over the selected period, sorted by total credits deducted descending. Each row carries the account identity (UUID + display name + primary email) and the aggregated spend so the admin dashboard can render a top-spenders table without joining client-side. Pair with [`GET /api/admins/credits/events?account_id=…&period=…`](/api-reference/admins/credits-events) to drill into the individual `usage_events` rows for a single account. Requires the authenticated account to be a Recoup admin.",
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "required": false,
            "description": "Rollup window. `daily` = today (last 1 day), `weekly` = last 7 days, `monthly` = last 30 days, `all` = no cutoff (every event ever recorded). Defaults to `monthly`. Follows the existing admin period convention.",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "daily",
                "weekly",
                "monthly"
              ],
              "default": "monthly"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size — number of accounts to return per request, sorted by total credits deducted descending. Defaults to 100; max 500.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "1-indexed page number. Server returns rows `(page - 1) * limit` through `page * limit - 1`. Defaults to 1. Use `total_count` in the response to drive a 'load more' control (`page * limit < total_count`).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Credit usage rollup retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminCreditsRollupResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid `period` or `limit` parameter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid credentials"
          },
          "403": {
            "description": "Forbidden - authenticated account is not a Recoup admin"
          },
          "500": {
            "description": "Internal server error while computing the rollup",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admins/credits/events": {
      "get": {
        "operationId": "getAdminsCreditsEvents",
        "description": "Returns the raw `usage_events` rows for a single account over the selected period, sorted by `created_at` descending. Powers the drilldown view that expands when a row in the [`/api/admins/credits/rollup`](/api-reference/admins/credits-rollup) table is opened. Each event represents one debit (main agent turn, subagent step, chat completion, or research call), with token counts and `credits_deducted` matching the wallet drop on `credits_usage` for that account.\n\nThe response also carries a `grants` array covering the same account and period: the admin credit grants made through [`POST /api/admins/credits`](/api-reference/admins/credits-grant). The two arrays answer different questions — `events` is what the system spent, `grants` is what a person set by hand, and only a grant carries an actor and a reason. Requires the authenticated account to be a Recoup admin.",
        "parameters": [
          {
            "name": "account_id",
            "in": "query",
            "required": true,
            "description": "UUID of the account whose `usage_events` rows to return.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "period",
            "in": "query",
            "required": false,
            "description": "Window to filter `created_at` against. Same semantics as the rollup endpoint. Defaults to `monthly`.",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "daily",
                "weekly",
                "monthly"
              ],
              "default": "monthly"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size — number of events to return per request, sorted by `created_at` descending. Defaults to 100; max 500.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "1-indexed page number. Server returns rows `(page - 1) * limit` through `page * limit - 1`. Defaults to 1. Use `total_count` in the response to drive a 'load more' control on the drilldown (`page * limit < total_count`).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Usage events retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminCreditsEventsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid `account_id`, `period`, or `limit`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid credentials"
          },
          "403": {
            "description": "Forbidden - authenticated account is not a Recoup admin"
          },
          "500": {
            "description": "Internal server error while fetching usage events",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/agents/signup": {
      "post": {
        "operationId": "postAgentsSignup",
        "description": "Register an agent. For new agent+ emails, returns an API key immediately. For all other cases, sends a verification code to the email — call [POST /api/agents/verify](/api-reference/agents/verify) with the code to get your API key.\n\n**Tip:** If you're unsure what email to register, generate a unique `agent+{suffix}@recoupable.com` address (e.g. `agent+1744410896-28439@recoupable.com`, combining a Unix timestamp with a random integer). This guarantees a fresh `agent+` address on every call — including multiple signups within the same second — and returns an API key instantly with no email verification required.",
        "security": [],
        "requestBody": {
          "description": "Agent email to register",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentSignupRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Signup processed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentSignupResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/agents/verify": {
      "post": {
        "operationId": "postAgentsVerify",
        "description": "Verify an agent's email with the code sent during signup. Returns an API key on success.",
        "security": [],
        "requestBody": {
          "description": "Email and verification code",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentVerifyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verification successful",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentVerifyResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid or expired verification code",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many failed verification attempts",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/admins/coding-agent/slack-tags": {
      "get": {
        "operationId": "getAdminsCodingSlackAuthors",
        "description": "Returns distinct authors of collected Coding Agent mentions for an admin author selector. Requires the authenticated account to be a Recoup admin, using exactly one of x-api-key or Authorization Bearer. No query parameters are defined. Each authorized request runs the existing all-period Slack collector once, then deduplicates by Slack author ID, retains the first collected profile and sorts by display name using localeCompare; identical names do not merge different IDs. The result is authors in that collected data, not a complete all-time Slack directory. Existing channel access, retention, paginated history, first-page thread replies and partial-failure limits remain; partial collection can still produce an incomplete successful result. Thrown collection failures return 500. This call is not free cached metadata: a future caller must account for scan latency and quotas. The release adds no automatic caller, UI, polling, scheduled action, new Slack scope or Slack send. Production admin access, history coverage, latency and quotas were not verified by the source contract tests.",
        "parameters": [],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Distinct collected authors; an empty collected dataset returns total 0 and tags [].",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminCodingSlackAuthorsResponse"
                },
                "examples": {
                  "collectedAuthors": {
                    "summary": "Synthetic distinct authors; the first collected Bob profile has no avatar.",
                    "value": {
                      "status": "success",
                      "total": 2,
                      "tags": [
                        {
                          "id": "U1",
                          "name": "Alice",
                          "avatar": null
                        },
                        {
                          "id": "U2",
                          "name": "Bob",
                          "avatar": null
                        }
                      ]
                    }
                  },
                  "noAuthors": {
                    "summary": "No collected authors.",
                    "value": {
                      "status": "success",
                      "total": 0,
                      "tags": []
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, conflicting or invalid credentials; inspect error or message according to the authentication envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminCodingSlackAuthenticationError"
                }
              }
            }
          },
          "403": {
            "description": "The authenticated account is not a Recoup admin.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Thrown collection failure with a generic server message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admins/agent-signups": {
      "get": {
        "operationId": "getAdminsAgentSignupMetadata",
        "summary": "List agent-prefixed API-key metadata (Admin)",
        "description": "Read API-key record metadata associated with current account emails matching the case-insensitive agent+ prefix. Authenticate with exactly one x-api-key or Authorization: Bearer credential for a Recoup admin account. Admin access is checked before query validation or metadata access.\n\nEach returned record contains only id, name, email and created_at. id identifies an API-key record, not an account or credential; no API key value or hash is selected or returned. email is the first matching current associated email, not necessarily a primary or canonical address. Multiple matching emails do not multiply a key record; multiple keys on one account remain separate records. Deleted keys are absent; expired key records are not excluded. Current email associations can change. This is a current-email metadata selection, not evidence of origin from POST /api/agents/signup, a unique-agent/account count, active-key count, usage or adoption.\n\nperiod defaults to all. Other values use inclusive midnight-UTC calendar boundaries on API-key record created_at: daily is today; weekly includes today and the preceding six calendar days; monthly includes today and the preceding 29 calendar days. Rows are ordered by key-record created_at descending. total is the length of the returned signups array, not a separate database-wide count. Existing database visibility and server row limits apply; no pagination or collection-completeness guarantee is provided. A successful empty read returns total 0 and signups []; a read failure returns a masked 500 instead.\n\nThis is GET /api/admins/agent-signups. The former GET /api/admins/agent/signups remains unavailable. The broader reporting decision in Mono #327 and original API #428 are not closed by this metadata route. Source tests use synthetic credential and storage boundaries; they do not prove production admin access, real data completeness or customer adoption. No UI, automatic caller, polling job, export or account/key creation is added.",
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "required": false,
            "description": "Optional key-record creation window, inclusive from 00:00 UTC: daily = today; weekly = 7 calendar days including today; monthly = 30 calendar days including today; all = no cutoff. Defaults to all when omitted; an explicit empty or unsupported value returns 400. This is not a rolling 24-hour window and does not filter by account or email creation time.",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "daily",
                "weekly",
                "monthly"
              ],
              "default": "all"
            },
            "example": "all"
          }
        ],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Returned API-key metadata and the count of these returned records.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminAgentKeyMetadataResponse"
                },
                "examples": {
                  "multipleKeys": {
                    "summary": "Synthetic example: two key records share one current matching email; total is not unique accounts.",
                    "value": {
                      "status": "success",
                      "total": 2,
                      "signups": [
                        {
                          "id": "11111111-1111-4111-8111-111111111112",
                          "name": "Second agent key",
                          "email": "agent+fixture@example.invalid",
                          "created_at": "2026-10-21T12:00:00Z"
                        },
                        {
                          "id": "11111111-1111-4111-8111-111111111111",
                          "name": "First agent key",
                          "email": "agent+fixture@example.invalid",
                          "created_at": "2026-10-20T12:00:00Z"
                        }
                      ]
                    }
                  },
                  "noRecords": {
                    "summary": "Successful empty metadata read, subject to existing visibility and collection limits.",
                    "value": {
                      "status": "success",
                      "total": 0,
                      "signups": []
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid or explicitly empty period, after successful admin authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing, simultaneous or invalid credentials; inspect error or message according to the authentication envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ErrorEnvelope"
                    },
                    {
                      "$ref": "#/components/schemas/AccountErrorResponse"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "The authenticated account is not a Recoup admin.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Metadata read or handler failure. Generic Internal server error message; not an empty success report.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer"
      },
      "apiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Your Recoup API key. [Learn more](/quickstart#api-keys)."
      }
    },
    "schemas": {
      "OrganizationProfessional": {
        "type": "object",
        "required": [
          "id",
          "organization_id",
          "name",
          "roles",
          "confirmed_by",
          "confirmation_basis",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "roles": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "songwriter",
                "producer"
              ]
            }
          },
          "confirmed_by": {
            "type": "string",
            "format": "uuid"
          },
          "confirmation_basis": {
            "type": "string",
            "enum": [
              "operator_confirmed"
            ],
            "description": "Operator assertion for this organization; not a globally verified person identity."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "AdminGrantCreditsRequest": {
        "type": "object",
        "required": [
          "account_id",
          "remaining_credits",
          "reason"
        ],
        "properties": {
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the account whose balance is being set. Must be an existing account — an unknown UUID is a 404, not a silent no-op."
          },
          "remaining_credits": {
            "type": "integer",
            "minimum": 0,
            "description": "The balance to leave the account holding, in credits (1 credit = 1 US cent). Absolute, not a delta. Zero is allowed — it is how an account is deliberately zeroed out. Negative values are rejected with a 400, even though ordinary usage can overdraw a balance below zero on its own."
          },
          "reason": {
            "type": "string",
            "minLength": 1,
            "description": "Why the grant was made, in plain language — e.g. `Trial headroom for the Aug 12 label demo`. Required and non-empty (a whitespace-only string is rejected): this is the field that makes a grant distinguishable from a Stripe top-up or a monthly reset when someone asks months later. Stored verbatim and returned by the events endpoint."
          }
        }
      },
      "AdminGrantCreditsResponse": {
        "type": "object",
        "required": [
          "status",
          "grant_id",
          "account_id",
          "remaining_credits",
          "previous_credits",
          "reason",
          "granted_by",
          "granted_at"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ],
            "description": "Status of the request"
          },
          "grant_id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the recorded grant row. Matches the `id` of the corresponding entry in the `grants` array of `GET /api/admins/credits/events`."
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the account whose balance was set (echoes the request)"
          },
          "remaining_credits": {
            "type": "integer",
            "description": "The balance the account now holds — the value supplied in the request"
          },
          "previous_credits": {
            "type": "integer",
            "nullable": true,
            "description": "The balance immediately before the grant. Null when the account had no credits row at all and one was created by this request."
          },
          "reason": {
            "type": "string",
            "description": "The reason recorded with the grant (echoes the request)"
          },
          "granted_by": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the admin account that made the grant, resolved from the credentials on the request. Never taken from the body."
          },
          "granted_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the grant was recorded"
          }
        }
      },
      "AdminGrantCreditsValidationError": {
        "type": "object",
        "required": [
          "status",
          "error"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "error"
            ],
            "description": "Status of the request"
          },
          "missing_fields": {
            "type": "array",
            "description": "JSON path segments of the first field that failed validation, e.g. `[\"reason\"]`. Absent when the body was not valid JSON at all.",
            "items": {
              "oneOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            }
          },
          "error": {
            "type": "string",
            "description": "Error message describing what went wrong"
          }
        }
      },
      "AdminCreditsRollupResponse": {
        "type": "object",
        "required": [
          "status",
          "period",
          "page",
          "limit",
          "total_count",
          "rows"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success",
              "error"
            ],
            "description": "Status of the request"
          },
          "period": {
            "type": "string",
            "enum": [
              "all",
              "daily",
              "weekly",
              "monthly"
            ],
            "description": "The period the response was computed over (echoes the request)"
          },
          "page": {
            "type": "integer",
            "minimum": 1,
            "description": "1-indexed page returned (echoes the request, or 1 if omitted)"
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "description": "Page size used for this response (echoes the request, or the default if omitted)"
          },
          "total_count": {
            "type": "integer",
            "minimum": 0,
            "description": "Total number of distinct accounts with at least one `usage_events` row in the selected period (i.e. the size of the full result set before pagination). The client derives `has_more` as `page * limit < total_count` and shows 'X of Y accounts'. Computed via a `COUNT(DISTINCT account_id)` query alongside the paginated row fetch."
          },
          "rows": {
            "type": "array",
            "description": "Per-account credit usage totals, sorted by `total_credits_deducted` descending",
            "items": {
              "type": "object",
              "required": [
                "account_id",
                "total_credits_deducted",
                "event_count"
              ],
              "properties": {
                "account_id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "UUID of the account"
                },
                "account_name": {
                  "type": "string",
                  "nullable": true,
                  "description": "Display name from the `accounts` table; null if the account has no name set"
                },
                "account_email": {
                  "type": "string",
                  "format": "email",
                  "nullable": true,
                  "description": "Primary email from `account_emails` joined for human-readable rows; null if no email is on file"
                },
                "total_credits_deducted": {
                  "type": "integer",
                  "description": "Sum of `usage_events.credits_deducted` across every event for this account in the selected period, in micro-dollars (1,000,000 = $1.00)"
                },
                "event_count": {
                  "type": "integer",
                  "description": "Number of `usage_events` rows aggregated into this total"
                }
              }
            }
          },
          "error": {
            "type": "string",
            "description": "Error message (only present if status is 'error')"
          }
        }
      },
      "AdminCreditsEventsResponse": {
        "type": "object",
        "required": [
          "status",
          "account_id",
          "period",
          "page",
          "limit",
          "total_count",
          "events",
          "grants"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success",
              "error"
            ],
            "description": "Status of the request"
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the account whose events were returned (echoes the request)"
          },
          "period": {
            "type": "string",
            "enum": [
              "all",
              "daily",
              "weekly",
              "monthly"
            ],
            "description": "The period the response was filtered to (echoes the request)"
          },
          "page": {
            "type": "integer",
            "minimum": 1,
            "description": "1-indexed page returned (echoes the request, or 1 if omitted)"
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "description": "Page size used for this response (echoes the request, or the default if omitted)"
          },
          "total_count": {
            "type": "integer",
            "minimum": 0,
            "description": "Total number of `usage_events` rows for this account in the selected period (i.e. the size of the full result set before pagination). The client derives `has_more` as `page * limit < total_count` and shows 'X of Y events'. Computed via a `COUNT(*)` query alongside the paginated row fetch."
          },
          "events": {
            "type": "array",
            "description": "Raw `usage_events` rows, sorted by `created_at` descending",
            "items": {
              "type": "object",
              "required": [
                "id",
                "created_at",
                "source",
                "agent_type",
                "input_tokens",
                "cached_input_tokens",
                "output_tokens",
                "tool_call_count",
                "credits_deducted"
              ],
              "properties": {
                "id": {
                  "type": "string",
                  "description": "nanoid primary key of the `usage_events` row"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When the event was recorded"
                },
                "source": {
                  "type": "string",
                  "enum": [
                    "web",
                    "api"
                  ],
                  "description": "Which surface originated the debit. `web` = open-agents chat. `api` = recoupable api (chat completion or research call)."
                },
                "agent_type": {
                  "type": "string",
                  "enum": [
                    "main",
                    "subagent"
                  ],
                  "description": "`main` for the top-level agent turn or any non-agent debit; `subagent` for a nested task-tool step"
                },
                "provider": {
                  "type": "string",
                  "nullable": true,
                  "description": "Provider slug (e.g. `anthropic`). Null when the debit isn't tied to a specific provider (e.g. research)."
                },
                "model_id": {
                  "type": "string",
                  "nullable": true,
                  "description": "The model for LLM-backed debits (e.g. `anthropic/claude-opus-4.6`), otherwise the billed API endpoint as `METHOD /route/pattern` (e.g. `POST /api/research/web`). Null on rows written before 2026-08-27."
                },
                "input_tokens": {
                  "type": "integer",
                  "description": "Total input tokens for the call (including cached). 0 for non-LLM debits."
                },
                "cached_input_tokens": {
                  "type": "integer",
                  "description": "Subset of `input_tokens` that hit the provider cache (priced at the cache-read rate)."
                },
                "output_tokens": {
                  "type": "integer",
                  "description": "Output tokens for the call. 0 for non-LLM debits."
                },
                "tool_call_count": {
                  "type": "integer",
                  "description": "Recorded tool count for this event. For the main agent workflow, this counts tool entries in the accumulated assistant reply, including pending and failed requests and entries retained when that reply resumes. Nested subagent entries are excluded. The value describes the reply snapshot, rather than successful executions or only new work after a resume. A writer can default an omitted count to zero, so zero alone does not establish that no tools were requested. Older events retain their previously recorded counts."
                },
                "credits_deducted": {
                  "type": "integer",
                  "description": "The amount debited from `credits_usage.remaining_credits` for this event, in micro-dollars (1,000,000 = $1.00). Same value the wallet dropped by on this turn."
                },
                "resource_url": {
                  "type": "string",
                  "nullable": true,
                  "description": "App-relative path of what produced the debit (`/chat?roomId=<roomId>`, `/music/<generationId>`, `/tasks/<taskId>/runs/<runId>`). Null for plain API calls and for rows written before the field existed."
                }
              }
            }
          },
          "grants": {
            "type": "array",
            "description": "Admin credit grants made against this account in the selected period, sorted by `created_at` descending — the write-side counterpart to `events`. A grant is a staff member setting the balance through [`POST /api/admins/credits`](/api-reference/admins/credits-grant), so unlike an event it carries an actor and a reason. Not paginated by `page`/`limit` and not counted in `total_count`, which describe `usage_events` only; capped at the 500 most recent grants in the period. Empty for the overwhelming majority of accounts, which have never been granted anything.",
            "items": {
              "type": "object",
              "required": [
                "id",
                "account_id",
                "created_at",
                "granted_by",
                "reason",
                "previous_credits",
                "remaining_credits"
              ],
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "UUID of the grant row — the `grant_id` returned by `POST /api/admins/credits`"
                },
                "account_id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "UUID of the account the grant was made against. Always equal to the top-level `account_id`, since the endpoint reports on one account at a time; present because each entry is the full stored grant row."
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When the grant was made"
                },
                "granted_by": {
                  "type": "string",
                  "format": "uuid",
                  "description": "UUID of the admin account that made the grant"
                },
                "reason": {
                  "type": "string",
                  "description": "The reason the admin recorded for the grant, verbatim"
                },
                "previous_credits": {
                  "type": "integer",
                  "nullable": true,
                  "description": "Balance immediately before the grant. Null when the account had no credits row and the grant created one."
                },
                "remaining_credits": {
                  "type": "integer",
                  "description": "Balance the account was left holding by the grant"
                }
              }
            }
          },
          "error": {
            "type": "string",
            "description": "Error message (only present if status is 'error')"
          }
        }
      },
      "ArtistsProResponse": {
        "type": "object",
        "required": [
          "status",
          "artists"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success",
              "error"
            ],
            "description": "Status of the request"
          },
          "artists": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "List of artist IDs owned by pro accounts"
          },
          "error": {
            "type": "string",
            "description": "Error message (only present if status is 'error')"
          }
        }
      },
      "Account": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier for the account"
          },
          "name": {
            "type": "string",
            "description": "Account display name"
          },
          "image": {
            "type": "string",
            "nullable": true,
            "description": "Profile image URL"
          },
          "instruction": {
            "type": "string",
            "nullable": true,
            "description": "Custom AI instructions for this account"
          },
          "knowledges": {
            "type": "array",
            "nullable": true,
            "items": {
              "$ref": "#/components/schemas/Knowledge"
            },
            "description": "Knowledge base files attached to this account"
          },
          "email": {
            "type": "string",
            "nullable": true,
            "description": "Primary email address"
          },
          "wallet_address": {
            "type": "string",
            "nullable": true,
            "description": "Connected wallet address"
          }
        }
      },
      "AccountData": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The unique identifier of the account"
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "The account ID (same as id, for consistency)"
          },
          "name": {
            "type": "string",
            "description": "Display name of the account"
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Email address associated with the account"
          },
          "wallet": {
            "type": "string",
            "description": "Wallet address associated with the account"
          },
          "image": {
            "type": "string",
            "format": "uri",
            "description": "URL of the account's profile image"
          },
          "instruction": {
            "type": "string",
            "description": "Custom instruction or bio"
          },
          "organization": {
            "type": "string",
            "description": "Organization name"
          },
          "job_title": {
            "type": "string",
            "description": "Job title"
          },
          "role_type": {
            "type": "string",
            "description": "Role type"
          },
          "company_name": {
            "type": "string",
            "description": "Company name"
          },
          "knowledges": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Knowledge"
            },
            "description": "Knowledge base files attached to this account"
          }
        }
      },
      "AccountDataResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/AccountData",
            "description": "The account data"
          }
        }
      },
      "AccountErrorResponse": {
        "type": "object",
        "required": [
          "status",
          "message"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "error"
            ],
            "description": "Status of the request"
          },
          "message": {
            "type": "string",
            "description": "Error message describing what went wrong"
          }
        }
      },
      "AccountSandboxRow": {
        "type": "object",
        "required": [
          "account_id",
          "total_sandboxes",
          "last_created_at"
        ],
        "properties": {
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "The unique identifier of the account",
            "example": "04e3aba9-c130-4fb8-8b92-34e95d43e66b"
          },
          "total_sandboxes": {
            "type": "integer",
            "description": "Total number of sandboxes created for this account",
            "example": 5
          },
          "last_created_at": {
            "type": "string",
            "format": "date-time",
            "description": "ISO 8601 timestamp of the most recently created sandbox for this account",
            "example": "2026-03-10T12:00:00Z"
          },
          "account_email": {
            "type": "string",
            "nullable": true,
            "description": "The email address of the account. Null if the account has no email set.",
            "example": "alice@example.com"
          }
        },
        "description": ""
      },
      "AddArtistSuccessResponse": {
        "type": "object",
        "required": [
          "success"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ],
            "description": "Indicates the artist was successfully added"
          }
        }
      },
      "AddArtistToAccountRequest": {
        "type": "object",
        "required": [
          "email",
          "artistId"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "description": "Email address of the account to add the artist to"
          },
          "artistId": {
            "type": "string",
            "format": "uuid",
            "description": "The unique identifier of the artist to add"
          }
        }
      },
      "AddArtistToOrganizationRequest": {
        "type": "object",
        "required": [
          "artistId",
          "organizationId"
        ],
        "properties": {
          "artistId": {
            "type": "string",
            "format": "uuid",
            "description": "The account ID of the artist to add",
            "example": "artist-account-uuid"
          },
          "organizationId": {
            "type": "string",
            "format": "uuid",
            "description": "The account ID of the organization",
            "example": "org-account-uuid"
          }
        }
      },
      "AddArtistToOrganizationResponse": {
        "type": "object",
        "required": [
          "status",
          "id"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ],
            "description": "Status of the request"
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the created artist-organization link"
          }
        }
      },
      "AddOrganizationMemberRequest": {
        "type": "object",
        "required": [
          "organizationId"
        ],
        "properties": {
          "organizationId": {
            "type": "string",
            "format": "uuid",
            "description": "The account ID of the organization"
          },
          "accountId": {
            "type": "string",
            "format": "uuid",
            "description": "The account ID of the member to add. Provide exactly one of accountId or email."
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Email of the member to add. The account is created if it does not exist yet. Provide exactly one of accountId or email."
          }
        }
      },
      "AddOrganizationMemberResponse": {
        "type": "object",
        "required": [
          "status",
          "id",
          "account_id"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ],
            "description": "Status of the request"
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the membership record"
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "The account ID of the member (resolved from email when email was provided)"
          }
        }
      },
      "RemoveOrganizationMemberResponse": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ],
            "description": "Status of the request"
          }
        }
      },
      "OrganizationDomain": {
        "type": "object",
        "required": [
          "id",
          "domain",
          "organization_id"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the domain mapping record"
          },
          "domain": {
            "type": "string",
            "description": "The email domain (lowercase, no @)",
            "example": "seekermusic.com"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid",
            "description": "The account ID of the organization"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the mapping was created"
          }
        }
      },
      "GetOrganizationDomainsResponse": {
        "type": "object",
        "required": [
          "status",
          "domains"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ],
            "description": "Status of the request"
          },
          "domains": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrganizationDomain"
            },
            "description": "Domains mapped to the organization"
          }
        }
      },
      "AddOrganizationDomainRequest": {
        "type": "object",
        "required": [
          "organizationId",
          "domain"
        ],
        "properties": {
          "organizationId": {
            "type": "string",
            "format": "uuid",
            "description": "The account ID of the organization"
          },
          "domain": {
            "type": "string",
            "description": "The email domain to map (lowercase, no @)",
            "example": "seekermusic.com"
          }
        }
      },
      "AddOrganizationDomainResponse": {
        "type": "object",
        "required": [
          "status",
          "id",
          "domain",
          "organization_id"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ],
            "description": "Status of the request"
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the domain mapping record"
          },
          "domain": {
            "type": "string",
            "description": "The mapped email domain",
            "example": "seekermusic.com"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid",
            "description": "The account ID of the organization"
          }
        }
      },
      "RemoveOrganizationDomainResponse": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ],
            "description": "Status of the request"
          }
        }
      },
      "AdminEmailsResponse": {
        "type": "object",
        "required": [
          "status",
          "emails"
        ],
        "description": "Response containing Resend emails sent for an account",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success",
              "error"
            ],
            "description": "Status of the request"
          },
          "emails": {
            "type": "array",
            "description": "List of emails sent for the account, ordered by created_at descending",
            "items": {
              "$ref": "#/components/schemas/PulseEmailRow"
            }
          }
        }
      },
      "AdminSandboxOrgsResponse": {
        "type": "object",
        "required": [
          "status",
          "repos"
        ],
        "description": "Response containing commit statistics for all org repositories",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success",
              "error"
            ],
            "description": "Status of the request"
          },
          "repos": {
            "type": "array",
            "description": "List of org repos with their commit statistics, ordered by total_commits descending",
            "items": {
              "$ref": "#/components/schemas/OrgRepoRow"
            }
          }
        }
      },
      "AdminSandboxesResponse": {
        "type": "object",
        "required": [
          "status",
          "accounts"
        ],
        "description": "Response containing per-account sandbox statistics for admin use",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success",
              "error"
            ],
            "description": "Status of the request"
          },
          "accounts": {
            "type": "array",
            "description": "List of accounts with their sandbox statistics, ordered by most recently active first",
            "items": {
              "$ref": "#/components/schemas/AccountSandboxRow"
            }
          }
        }
      },
      "CheckAdminResponse": {
        "type": "object",
        "required": [
          "status",
          "isAdmin"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ],
            "description": "Status of the request"
          },
          "isAdmin": {
            "type": "boolean",
            "description": "Whether the authenticated account is a Recoup admin"
          }
        }
      },
      "CreateAccountRequest": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "description": "Email address to associate with the account. If an account with this email exists, it will be returned."
          },
          "wallet": {
            "type": "string",
            "description": "Wallet address to associate with the account. If an account with this wallet exists, it will be returned."
          }
        },
        "description": "At least one of email or wallet should be provided to identify or create an account."
      },
      "SendEmailRequest": {
        "type": "object",
        "properties": {
          "to": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "string",
              "format": "email"
            },
            "description": "Recipient email address(es). Optional — when omitted, the email is sent to the authenticated account's own email address. Without a payment method on file, restricted to the account's own email; [add a payment method](/api-reference/credits/sessions-create) to send to any recipient.",
            "example": [
              "recipient@example.com"
            ]
          },
          "cc": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            },
            "description": "Optional CC email addresses. Without a payment method on file, restricted to the account's own email; [add a payment method](/api-reference/credits/sessions-create) to send to any recipient.",
            "example": [
              "cc@example.com"
            ]
          },
          "subject": {
            "type": "string",
            "description": "Email subject line. Optional — when omitted, defaults to the first heading or line of the body, falling back to `Message from Recoup` if the body is empty.",
            "example": "Weekly Pulse Report"
          },
          "text": {
            "type": "string",
            "description": "Plain text or Markdown body. Rendered as HTML via Markdown if no `html` is provided.",
            "example": "# Pulse Report\n\nHere's your weekly summary."
          },
          "html": {
            "type": "string",
            "description": "Raw HTML body. Takes precedence over `text` when both are provided.",
            "example": "<h1>Pulse Report</h1><p>Here's your weekly summary.</p>"
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Optional custom email headers"
          },
          "chat_id": {
            "type": "string",
            "description": "Chat ID to include a chat link in the email footer. Use [Create Chat](/api-reference/chat/create) to create one."
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the account to send the email for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, sends for the API key's own account."
          }
        }
      },
      "EmailResponse": {
        "type": "object",
        "required": [
          "success",
          "message",
          "id"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Whether the email was sent successfully",
            "example": true
          },
          "message": {
            "type": "string",
            "description": "Human-readable result message",
            "example": "Email sent successfully from Agent by Recoup <agent@recoupable.dev> to recipient@example.com."
          },
          "id": {
            "type": "string",
            "description": "Resend email ID",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          }
        }
      },
      "CreateOrganizationRequest": {
        "type": "object",
        "required": [
          "name",
          "accountId"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "The name of the organization to create",
            "example": "My New Label"
          },
          "accountId": {
            "type": "string",
            "format": "uuid",
            "description": "The account ID of the creator",
            "example": "123e4567-e89b-12d3-a456-426614174000"
          }
        }
      },
      "CreateOrganizationResponse": {
        "type": "object",
        "required": [
          "status",
          "organization"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ],
            "description": "Status of the request"
          },
          "organization": {
            "$ref": "#/components/schemas/CreatedOrganization",
            "description": "The created organization"
          }
        }
      },
      "CreatedOrganization": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the new organization account"
          },
          "name": {
            "type": "string",
            "description": "Name of the organization"
          }
        }
      },
      "Error": {
        "required": [
          "error",
          "message"
        ],
        "type": "object",
        "properties": {
          "error": {
            "type": "integer",
            "format": "int32"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "GetAccountIdResponse": {
        "type": "object",
        "required": [
          "status",
          "accountId"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ],
            "description": "Status of the request"
          },
          "accountId": {
            "type": "string",
            "format": "uuid",
            "description": "The unique identifier (UUID) of the authenticated account"
          }
        }
      },
      "GetAccountResponse": {
        "type": "object",
        "required": [
          "status",
          "account"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ],
            "description": "Status of the request"
          },
          "account": {
            "$ref": "#/components/schemas/Account",
            "description": "The account details"
          }
        }
      },
      "GetOrganizationsResponse": {
        "type": "object",
        "required": [
          "status",
          "organizations"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ],
            "description": "Status of the request"
          },
          "organizations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Organization"
            },
            "description": "List of organizations the account belongs to"
          }
        }
      },
      "Knowledge": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "URL to the knowledge file"
          },
          "name": {
            "type": "string",
            "description": "Name of the knowledge file"
          },
          "type": {
            "type": "string",
            "description": "MIME type of the file"
          }
        }
      },
      "OrgRepoRow": {
        "type": "object",
        "required": [
          "repo_name",
          "repo_url",
          "total_commits",
          "latest_commit_messages",
          "earliest_committed_at",
          "latest_committed_at",
          "account_repos"
        ],
        "description": "Commit statistics for a single GitHub org repository",
        "properties": {
          "repo_name": {
            "type": "string",
            "description": "Repository name",
            "example": "chat"
          },
          "repo_url": {
            "type": "string",
            "description": "Full GitHub HTML URL of the repository",
            "example": "https://github.com/recoupable/chat"
          },
          "total_commits": {
            "type": "integer",
            "description": "Total number of commits in the repository",
            "example": 5696
          },
          "latest_commit_messages": {
            "type": "array",
            "description": "Messages from the 5 most recent commits",
            "items": {
              "type": "string"
            },
            "example": [
              "Merge test into main",
              "fix: duration stuck at 0ms for in-progress tasks"
            ]
          },
          "earliest_committed_at": {
            "type": "string",
            "format": "date-time",
            "description": "ISO 8601 timestamp of the earliest (first) commit",
            "example": "2024-09-27T17:16:01Z"
          },
          "latest_committed_at": {
            "type": "string",
            "format": "date-time",
            "description": "ISO 8601 timestamp of the most recent commit",
            "example": "2026-03-10T19:57:37Z"
          },
          "account_repos": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "account_id": {
                  "type": "string"
                },
                "email": {
                  "type": "string",
                  "nullable": true
                },
                "repo_url": {
                  "type": "string"
                }
              },
              "required": [
                "account_id",
                "repo_url"
              ]
            },
            "description": "List of accounts using this org repo as a submodule, with account_id, email, and repo_url"
          }
        }
      },
      "Organization": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the membership record"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the organization account"
          },
          "organization_name": {
            "type": "string",
            "description": "Display name of the organization"
          },
          "organization_image": {
            "type": "string",
            "nullable": true,
            "description": "Organization logo/image URL"
          }
        }
      },
      "OrganizationsErrorResponse": {
        "type": "object",
        "required": [
          "status",
          "message"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "error"
            ],
            "description": "Status of the request"
          },
          "message": {
            "type": "string",
            "description": "Error message describing what went wrong"
          }
        }
      },
      "ErrorEnvelope": {
        "type": "object",
        "required": [
          "status",
          "error"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "error"
            ],
            "description": "Status of the request"
          },
          "error": {
            "type": "string",
            "description": "Error message describing what went wrong"
          }
        }
      },
      "Pulse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier for the pulse"
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier for the associated account"
          },
          "active": {
            "type": "boolean",
            "description": "Whether the pulse is active (defaults to true)"
          }
        }
      },
      "PulseEmailRow": {
        "type": "object",
        "required": [
          "id",
          "from",
          "to",
          "subject",
          "created_at",
          "last_event"
        ],
        "description": "A single email record from Resend (full GetEmailResponseSuccess). See [Resend API docs](https://resend.com/docs/api-reference/emails/retrieve-email) for the source of truth.",
        "properties": {
          "id": {
            "type": "string",
            "description": "The Resend email ID"
          },
          "from": {
            "type": "string",
            "description": "Sender email address"
          },
          "to": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Recipient email addresses"
          },
          "cc": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true,
            "description": "CC recipient email addresses"
          },
          "bcc": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true,
            "description": "BCC recipient email addresses"
          },
          "reply_to": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true,
            "description": "Reply-to email addresses"
          },
          "subject": {
            "type": "string",
            "description": "Email subject line"
          },
          "html": {
            "type": "string",
            "nullable": true,
            "description": "HTML content of the email"
          },
          "text": {
            "type": "string",
            "nullable": true,
            "description": "Plain text content of the email"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the email was created"
          },
          "scheduled_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Scheduled send time, if any"
          },
          "last_event": {
            "type": "string",
            "enum": [
              "bounced",
              "canceled",
              "clicked",
              "complained",
              "delivered",
              "delivery_delayed",
              "failed",
              "opened",
              "queued",
              "scheduled",
              "sent"
            ],
            "description": "Most recent delivery event for this email"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "value": {
                  "type": "string"
                }
              },
              "required": [
                "name",
                "value"
              ]
            },
            "nullable": true,
            "description": "Custom tags attached to the email"
          }
        }
      },
      "PulsesResponse": {
        "type": "object",
        "required": [
          "status",
          "pulses"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success",
              "error"
            ],
            "description": "Status of the request"
          },
          "pulses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Pulse"
            },
            "description": "Array of pulse objects. Contains pulses for the authenticated account. If the account has access to organizations, all organization accounts are included."
          },
          "error": {
            "type": "string",
            "description": "Error message (only present if status is error)"
          }
        }
      },
      "UpdateAccountRequest": {
        "type": "object",
        "required": [
          "accountId"
        ],
        "properties": {
          "accountId": {
            "type": "string",
            "format": "uuid",
            "description": "The unique identifier of the account to update"
          },
          "name": {
            "type": "string",
            "description": "Display name for the account"
          },
          "instruction": {
            "type": "string",
            "description": "Custom instruction or bio for the account"
          },
          "organization": {
            "type": "string",
            "description": "Organization name associated with the account"
          },
          "image": {
            "type": "string",
            "format": "uri",
            "description": "URL of the account's profile image"
          },
          "jobTitle": {
            "type": "string",
            "description": "Job title of the account holder"
          },
          "roleType": {
            "type": "string",
            "description": "Role type within the organization"
          },
          "companyName": {
            "type": "string",
            "description": "Company name associated with the account"
          },
          "knowledges": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Knowledge"
            },
            "description": "Knowledge base files attached to this account"
          }
        }
      },
      "UpdatePulseRequest": {
        "type": "object",
        "required": [
          "active"
        ],
        "properties": {
          "active": {
            "type": "boolean",
            "description": "Whether to enable or disable the pulse",
            "example": true
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the account to update the pulse for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, updates the pulse for the API key's own account."
          }
        }
      },
      "AgentSignupRequest": {
        "type": "object",
        "required": [
          "email"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "description": "The agent email address. Emails with the agent+ prefix (e.g. agent+mybot@example.com) get an API key immediately on first signup.",
            "example": "agent+mybot@example.com"
          }
        }
      },
      "AgentSignupResponse": {
        "type": "object",
        "required": [
          "account_id",
          "message"
        ],
        "properties": {
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "The account ID for the registered agent.",
            "example": "123e4567-e89b-12d3-a456-426614174000"
          },
          "api_key": {
            "type": [
              "string",
              "null"
            ],
            "description": "API key returned immediately for new agent+ prefix emails. Null for all other cases — check your email for a verification code.",
            "example": "recoup_sk_abc123..."
          },
          "message": {
            "type": "string",
            "description": "Human-readable status message.",
            "example": "If this is a new agent+ email, your API key is included. Otherwise, check your email for a verification code."
          }
        }
      },
      "AgentVerifyRequest": {
        "type": "object",
        "required": [
          "email",
          "code"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "description": "The email address used during signup.",
            "example": "you@example.com"
          },
          "code": {
            "type": "string",
            "minLength": 6,
            "maxLength": 6,
            "pattern": "^[0-9]{6}$",
            "description": "The 6-digit verification code sent to the email.",
            "example": "123456"
          }
        }
      },
      "AgentVerifyResponse": {
        "type": "object",
        "required": [
          "account_id",
          "api_key",
          "message"
        ],
        "properties": {
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "The account ID for the verified agent.",
            "example": "123e4567-e89b-12d3-a456-426614174000"
          },
          "api_key": {
            "type": "string",
            "description": "API key for the verified account.",
            "example": "recoup_sk_abc123..."
          },
          "message": {
            "type": "string",
            "description": "Human-readable status message.",
            "example": "Verified"
          }
        }
      },
      "CreateSubscriptionSessionRequest": {
        "type": "object",
        "required": [
          "successUrl"
        ],
        "properties": {
          "plan": {
            "type": "string",
            "enum": [
              "starter",
              "pro"
            ],
            "description": "The plan to buy. Defaults to `pro` when omitted (back-compat for authenticated callers). `pro` carries the 30-day trial; `starter` charges on completion.",
            "example": "pro"
          },
          "successUrl": {
            "type": "string",
            "format": "uri",
            "description": "Where Stripe sends the buyer after payment. For anonymous checkout include the literal `{CHECKOUT_SESSION_ID}` placeholder so the client can call Claim Subscription if the sign-in email differs.",
            "example": "https://chat.recoupable.dev?checkout=success&session_id={CHECKOUT_SESSION_ID}"
          },
          "cancelUrl": {
            "type": "string",
            "format": "uri",
            "description": "Where Stripe sends the buyer if they leave Checkout without paying.",
            "example": "https://recoupable.dev/pricing"
          }
        }
      },
      "CreateCardOnFileSessionRequest": {
        "type": "object",
        "required": [
          "successUrl"
        ],
        "properties": {
          "successUrl": {
            "type": "string",
            "format": "uri",
            "description": "The URL Stripe redirects to after the card is saved.",
            "example": "https://chat.recoupable.dev?card=saved"
          }
        }
      },
      "CreateSubscriptionSessionResponse": {
        "type": "object",
        "required": [
          "id",
          "url"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The checkout session ID.",
            "example": "cs_test_a1b2c3d4e5f6g7h8i9j0"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "The hosted checkout URL. Redirect to this URL to complete Checkout.",
            "example": "https://checkout.stripe.com/pay/cs_test_a1b2c3d4e5f6g7h8i9j0"
          }
        }
      },
      "SubscriptionResponse": {
        "type": "object",
        "required": [
          "isPro",
          "status",
          "plan",
          "source",
          "name",
          "amountCents",
          "currency",
          "interval",
          "collectionMethod",
          "currentPeriodEnd"
        ],
        "properties": {
          "isPro": {
            "type": "boolean",
            "description": "True only for effective Pro entitlement. A paid Starter account returns false. Use plan for paid-plan decisions."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "trialing",
              "canceled",
              "past_due",
              "none"
            ],
            "description": "Current entitlement view. Resolving to Free returns none and null billing fields, including for an inactive subscription; this is not subscription lifecycle history.",
            "example": "active"
          },
          "plan": {
            "type": [
              "string",
              "null"
            ],
            "description": "Plan identifier (e.g. `pro`). Null when no subscription currently confers a paid plan.",
            "example": "pro",
            "enum": [
              "starter",
              "pro",
              null
            ]
          },
          "source": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "account",
              "organization",
              null
            ],
            "description": "Origin of the subscription. `account` for direct, `organization` when covered by an organization. Null when no subscription currently confers a paid plan.",
            "example": "account"
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Display name of the plan's Stripe price (nickname) or product. Null when no subscription exists.",
            "example": "Pro"
          },
          "amountCents": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Recurring amount in the smallest currency unit (cents for USD). Null when no subscription exists.",
            "example": 9900
          },
          "currency": {
            "type": [
              "string",
              "null"
            ],
            "description": "ISO 4217 currency code, lowercase.",
            "example": "usd"
          },
          "interval": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "day",
              "week",
              "month",
              "year",
              null
            ],
            "description": "Billing interval of the recurring price.",
            "example": "month"
          },
          "collectionMethod": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "charge_automatically",
              "send_invoice",
              null
            ],
            "description": "`charge_automatically` bills the card on file at renewal; `send_invoice` emails an invoice that is paid manually (enterprise plans). A saved card is never charged for a `send_invoice` plan.",
            "example": "charge_automatically"
          },
          "currentPeriodEnd": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "End of the current billing period: the renewal date, or the next invoice date for invoiced plans.",
            "example": "2026-10-04T00:00:00Z"
          }
        },
        "description": "Effective subscription details. When status is none, plan, source, name, amountCents, currency, interval, collectionMethod and currentPeriodEnd are all null."
      },
      "SubscriptionErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message.",
            "example": "Account not found"
          }
        }
      },
      "AccountCreditsResponse": {
        "type": "object",
        "required": [
          "account_id",
          "remaining_credits",
          "total_credits",
          "used_credits",
          "is_pro",
          "timestamp",
          "plan",
          "task_limit",
          "min_cadence_minutes"
        ],
        "properties": {
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "The unique identifier of the account this balance belongs to.",
            "example": "11111111-1111-4111-8111-111111111111"
          },
          "remaining_credits": {
            "type": "integer",
            "description": "Balance in integer micro-dollars. Can exceed the plan allowance after a top-up or be negative. This is a balance, not a lifetime-spend total.",
            "example": 292450000
          },
          "total_credits": {
            "type": "integer",
            "minimum": 0,
            "description": "Monthly refill floor in integer micro-dollars: Free 3,330,000; Starter 20,000,000; Pro 300,000,000. Top-ups can put remaining credits above this floor.",
            "example": 300000000
          },
          "used_credits": {
            "type": "integer",
            "minimum": 0,
            "description": "max(0, total_credits - remaining_credits). A balance-derived display, not lifetime or period ledger spend.",
            "example": 7550000
          },
          "is_pro": {
            "type": "boolean",
            "description": "True when the account is on a pro plan, directly via an account subscription or via an organization subscription.",
            "example": true
          },
          "timestamp": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "ISO 8601 timestamp from the balance record; null when unavailable.",
            "example": "2026-10-01T12:00:00Z"
          },
          "plan": {
            "type": "string",
            "enum": [
              "free",
              "starter",
              "pro"
            ],
            "example": "pro"
          },
          "task_limit": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Enabled scheduled-task limit; null means unlimited.",
            "example": null
          },
          "min_cadence_minutes": {
            "type": "integer",
            "description": "Minimum allowed cadence: Free 10080, Starter 1440, Pro 60.",
            "example": 60
          }
        },
        "example": {
          "account_id": "11111111-1111-4111-8111-111111111111",
          "remaining_credits": 292450000,
          "total_credits": 300000000,
          "used_credits": 7550000,
          "is_pro": true,
          "plan": "pro",
          "task_limit": null,
          "min_cadence_minutes": 60,
          "timestamp": "2026-10-01T12:00:00Z"
        },
        "description": "Current plan-derived allowance and balance in integer micro-dollars. Extra credits can exceed the allowance; used_credits is max(0, total_credits - remaining_credits), not ledger spend. The response preserves the signed balance. Null task_limit means unlimited."
      },
      "AccountUsageEvent": {
        "type": "object",
        "required": [
          "id",
          "created_at",
          "source",
          "agent_type",
          "provider",
          "model_id",
          "input_tokens",
          "cached_input_tokens",
          "output_tokens",
          "tool_call_count",
          "credits_deducted",
          "usd",
          "resource_url"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Identifier of the `usage_events` row.",
            "example": "3AANn3Ij9uF-zZIlW_zlP"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the charge was recorded, normalized to UTC at database microsecond precision.",
            "example": "2026-08-27T11:56:58.000000Z"
          },
          "source": {
            "type": "string",
            "description": "Which surface originated the charge: `api` for a request to the API, `web` for the chat app. Null when this field was not recorded.",
            "example": "api",
            "nullable": true
          },
          "agent_type": {
            "type": "string",
            "description": "`main` for a top-level request or any non-agent charge; `subagent` for a nested task step. Null when this field was not recorded.",
            "example": "main",
            "nullable": true
          },
          "provider": {
            "type": "string",
            "nullable": true,
            "description": "Provider slug when the charge is a model or generation call (for example `anthropic`, `fal`). Null for research and other fixed-price endpoints.",
            "example": "fal"
          },
          "model_id": {
            "type": "string",
            "nullable": true,
            "description": "The model for LLM-backed charges (a chat turn, a song generation), otherwise the API endpoint that was billed, as `METHOD /route/pattern` (for example `POST /api/artist/socials/scrape`). Null on rows written before 2026-08-27.",
            "example": "POST /api/artist/socials/scrape"
          },
          "input_tokens": {
            "type": "integer",
            "description": "Input tokens for the call, including cached. 0 for non-LLM charges. Null when this field was not recorded.",
            "example": 0,
            "nullable": true
          },
          "cached_input_tokens": {
            "type": "integer",
            "description": "Subset of `input_tokens` served from the provider cache. Null when this field was not recorded.",
            "example": 0,
            "nullable": true
          },
          "output_tokens": {
            "type": "integer",
            "description": "Output tokens for the call. 0 for non-LLM charges. Null when this field was not recorded.",
            "example": 0,
            "nullable": true
          },
          "tool_call_count": {
            "type": "integer",
            "description": "Recorded tool count for this event. For the main agent workflow, this counts tool entries in the accumulated assistant reply, including pending and failed requests and entries retained when that reply resumes. Nested subagent entries are excluded. The value describes the reply snapshot, rather than successful executions or only new work after a resume. A writer can default an omitted count to zero, so zero alone does not establish that no tools were requested. Older events retain their previously recorded counts. Null when this field was not recorded.",
            "example": 0,
            "nullable": true
          },
          "credits_deducted": {
            "type": "integer",
            "description": "Amount charged, as the raw ledger integer in micro-dollars (1,000,000 = $1.00). Divide by 1,000,000 for dollars.",
            "example": 20000
          },
          "usd": {
            "type": "string",
            "description": "`credits_deducted` formatted as US dollars with two decimals.",
            "example": "$0.02"
          },
          "resource_url": {
            "type": "string",
            "nullable": true,
            "description": "App-relative path of what produced the charge, when there is something to open: `/chat?roomId=<roomId>` for a chat turn, `/music/<generationId>` for a song, `/tasks/<taskId>/runs/<runId>` for a scheduled task run. Null for plain API calls and for rows written before the field existed.",
            "example": "/music/0c35429f-deb8-48f0-b0f2-fd5145de2583"
          }
        }
      },
      "AccountUsageResponse": {
        "type": "object",
        "required": [
          "account_id",
          "period",
          "total_credits_deducted",
          "total_usd",
          "events",
          "next_cursor"
        ],
        "properties": {
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "The account whose charges are listed.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "period": {
            "type": "object",
            "required": [
              "from",
              "to"
            ],
            "description": "The period the totals cover.",
            "properties": {
              "from": {
                "type": "string",
                "format": "date-time",
                "example": "2026-08-01T00:00:00.000Z"
              },
              "to": {
                "type": "string",
                "format": "date-time",
                "example": "2026-08-27T12:00:00.000Z"
              }
            }
          },
          "total_credits_deducted": {
            "type": "integer",
            "description": "Sum of `credits_deducted` over every charge in the period, in micro-dollars. Covers the whole period, not only this page.",
            "example": 70000
          },
          "total_usd": {
            "type": "string",
            "description": "`total_credits_deducted` formatted as US dollars.",
            "example": "$0.07"
          },
          "events": {
            "type": "array",
            "description": "Charges in the period in the requested `sort` order (newest first by default).",
            "items": {
              "$ref": "#/components/schemas/AccountUsageEvent"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true,
            "description": "Opaque; pass unchanged as cursor with the same sort, from and to. A full page may return a cursor followed by an empty final page; null means this traversal has ended. Time cursors retain timestamp and ID; cost cursors retain amount and ID.",
            "example": "v1:WyIyMDI2LTA4LTI3VDExOjU2OjU4LjAwMDAwMFoiLCIzQUFObjNJajl1Ri16WklsV196bFAiXQ"
          },
          "series_bucket": {
            "type": "string",
            "enum": [
              "hour",
              "day",
              "week",
              "month"
            ],
            "description": "Granularity of `series`, derived from the span of the period: `hour` up to 2 days, `day` up to 90 days, `week` up to 12 months, `month` beyond. Present only on a first page (no `cursor`).",
            "example": "day"
          },
          "series": {
            "type": "array",
            "description": "Spend over the period, one entry per `series_bucket` that had at least one charge, ascending by `start`, in UTC. The sum of `credits_deducted` across the entries equals `total_credits_deducted`. Present only on a first page (no `cursor`); omitted on cursor pages so paging never recomputes it.",
            "items": {
              "type": "object",
              "required": [
                "start",
                "credits_deducted",
                "usd",
                "events"
              ],
              "properties": {
                "start": {
                  "type": "string",
                  "format": "date-time",
                  "description": "Start of the bucket, UTC.",
                  "example": "2026-08-12T00:00:00.000Z"
                },
                "credits_deducted": {
                  "type": "integer",
                  "description": "Charges in the bucket, in micro-dollars.",
                  "example": 221090000
                },
                "usd": {
                  "type": "string",
                  "description": "`credits_deducted` formatted as US dollars.",
                  "example": "$221.09"
                },
                "events": {
                  "type": "integer",
                  "description": "Number of charges in the bucket.",
                  "example": 2462
                }
              }
            },
            "example": [
              {
                "start": "2026-08-11T00:00:00.000Z",
                "credits_deducted": 56080000,
                "usd": "$56.08",
                "events": 727
              },
              {
                "start": "2026-08-12T00:00:00.000Z",
                "credits_deducted": 221090000,
                "usd": "$221.09",
                "events": 2462
              },
              {
                "start": "2026-08-13T00:00:00.000Z",
                "credits_deducted": 440930000,
                "usd": "$440.93",
                "events": 5479
              }
            ]
          }
        }
      },
      "AccountCreditsErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message.",
            "example": "Account not found"
          }
        }
      },
      "SavedCard": {
        "type": "object",
        "required": [
          "brand",
          "last4",
          "exp_month",
          "exp_year",
          "funding"
        ],
        "properties": {
          "brand": {
            "type": "string",
            "description": "Card brand. Common values: `visa`, `mastercard`, `amex`, `discover`, `diners`, `jcb`, `unionpay`, `unknown`.",
            "example": "visa"
          },
          "last4": {
            "type": "string",
            "pattern": "^\\d{4}$",
            "description": "Last four digits of the card number. Safe to display in UI for identification.",
            "example": "4242"
          },
          "exp_month": {
            "type": "integer",
            "minimum": 1,
            "maximum": 12,
            "description": "Card expiration month (1-12). Compare against the current month to detect expired cards.",
            "example": 12
          },
          "exp_year": {
            "type": "integer",
            "description": "Card expiration year (full 4-digit year). Compare against the current year to detect expired cards.",
            "example": 2026
          },
          "funding": {
            "type": "string",
            "description": "Funding type. Common values: `credit`, `debit`, `prepaid`, `unknown`.",
            "example": "credit"
          }
        }
      },
      "AccountPaymentMethodResponse": {
        "type": "object",
        "required": [
          "account_id",
          "card"
        ],
        "properties": {
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "The unique identifier of the account this payment method belongs to.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "card": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/SavedCard"
              },
              {
                "type": "null"
              }
            ],
            "description": "Default card resolved by this lookup. `null` when the selected Stripe customer has no supported default card, including when no tagged customer exists. This describes the current lookup result; it does not establish whether the account previously saved a card or whether other cards remain attached."
          }
        }
      },
      "AccountPaymentMethodErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message.",
            "example": "Unauthorized"
          }
        }
      },
      "AccountPayment": {
        "type": "object",
        "required": [
          "id",
          "createdAt",
          "description",
          "amountCents",
          "currency",
          "status",
          "url"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stripe invoice id; use as `startingAfter` to page.",
            "example": "in_1U5xj400JObOnOb5BE0CmxCt"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the invoice was created.",
            "example": "2026-09-04T14:33:00Z"
          },
          "description": {
            "type": "string",
            "description": "What was billed: the first line item's description, or the plan name.",
            "example": "Pro, monthly"
          },
          "amountCents": {
            "type": "integer",
            "description": "Amount due in the smallest currency unit.",
            "example": 9900
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217 currency code, lowercase.",
            "example": "usd"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "open",
              "paid",
              "uncollectible",
              "void"
            ],
            "description": "Stripe invoice status.",
            "example": "paid"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "Hosted invoice page (receipt). Null for draft invoices.",
            "example": "https://invoice.stripe.com/i/acct_123/test_456"
          }
        }
      },
      "AccountPaymentsResponse": {
        "type": "object",
        "required": [
          "account_id",
          "payments",
          "hasMore"
        ],
        "properties": {
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "The account these payments belong to.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "payments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AccountPayment"
            },
            "description": "Invoices, newest first, merged across every Stripe customer tagged with the account id. Empty when the account has no tagged Stripe customer or no invoices."
          },
          "hasMore": {
            "type": "boolean",
            "description": "True when another page exists; pass the last `id` as `startingAfter`.",
            "example": false
          }
        }
      },
      "AccountPaymentsErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message.",
            "example": "Account not found"
          }
        }
      },
      "AutoTopUpResponse": {
        "type": "object",
        "required": [
          "account_id",
          "enabled",
          "amountCents",
          "thresholdCents",
          "lastRunAt",
          "lastError"
        ],
        "properties": {
          "account_id": {
            "type": "string",
            "format": "uuid",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether auto top-up is on. Off by default.",
            "example": true
          },
          "amountCents": {
            "type": "integer",
            "nullable": true,
            "description": "Amount charged and granted per top-up, in cents. Null until set.",
            "example": 10000
          },
          "thresholdCents": {
            "type": "integer",
            "nullable": true,
            "description": "Balance, in cents, below which a top-up runs. Null until set.",
            "example": 100
          },
          "lastRunAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "When the last auto top-up was attempted. Null until the first run.",
            "example": "2026-09-04T15:05:00Z"
          },
          "lastError": {
            "type": "string",
            "nullable": true,
            "description": "Stripe decline message from the attempt that turned auto top-up off. Null while healthy or once re-enabled.",
            "example": "Your card was declined."
          }
        }
      },
      "UpdateAutoTopUpRequest": {
        "type": "object",
        "required": [
          "enabled",
          "amountCents",
          "thresholdCents"
        ],
        "properties": {
          "enabled": {
            "type": "boolean",
            "example": true
          },
          "amountCents": {
            "type": "integer",
            "minimum": 500,
            "maximum": 100000,
            "description": "Amount to charge and grant per top-up, in cents (5.00 to 1,000.00 USD).",
            "example": 10000
          },
          "thresholdCents": {
            "type": "integer",
            "minimum": 0,
            "description": "Balance, in cents, below which a top-up runs. Must be below `amountCents`.",
            "example": 100
          }
        }
      },
      "AutoTopUpErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message.",
            "example": "Add a payment method before turning on auto top-up"
          }
        }
      },
      "CreateCreditsSessionRequest": {
        "type": "object",
        "required": [
          "credits",
          "successUrl"
        ],
        "properties": {
          "successUrl": {
            "type": "string",
            "format": "uri",
            "description": "Required valid redirect URL, including when a saved card is charged directly. Used by Checkout fallback; no default is supplied.",
            "example": "https://chat.recoupable.dev?credits=success"
          },
          "credits": {
            "type": "integer",
            "minimum": 10000,
            "description": "The number of credits to purchase, in integer micro-dollars (1,000,000 = \\$1.00), so the value in USD is `credits / 1000000`. Example: `2500000` is \\$2.50 worth of credits (the customer is also charged a Stripe processing fee on top).",
            "example": 2500000,
            "multipleOf": 10000
          },
          "accountId": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the account to create the session for. Only applicable when the authenticated account has admin access to multiple accounts. If not provided, creates a session for the API key's own account.",
            "example": "123e4567-e89b-12d3-a456-426614174000"
          }
        },
        "additionalProperties": false,
        "example": {
          "credits": 2500000,
          "successUrl": "https://chat.recoupable.dev?credits=success"
        }
      },
      "CreditsTopupResponse": {
        "type": "object",
        "description": "Top-up response. Two paths share this shape — clients can discriminate on the presence of `url` (Checkout fallback) vs `paymentIntentId` (auto-charged).",
        "properties": {
          "paymentIntentId": {
            "type": "string",
            "description": "**Auto-charge path only.** The Stripe PaymentIntent ID for the off-session charge. Useful for reconciliation and support. Omitted on the Checkout fallback path.",
            "example": "pi_3O1a2b3c4d5e6f7g_h8i9j0kL"
          },
          "creditsPurchased": {
            "type": "integer",
            "minimum": 1,
            "description": "**Auto-charge path only.** The number of credits purchased, matching the `credits` request field. These credits are added to the account's balance asynchronously via Stripe webhook (typically within seconds). Omitted on the Checkout fallback path.",
            "example": 2500000
          },
          "totalCents": {
            "type": "integer",
            "minimum": 1,
            "description": "Auto-charge path only. Whole cents: creditsPurchased / 10000 plus the processing fee. Example: 2,500,000 micro-dollars is 250 cents before fees.",
            "example": 289
          },
          "id": {
            "type": "string",
            "description": "**Checkout fallback only.** The Stripe Checkout Session ID. Omitted on the auto-charge path.",
            "example": "cs_test_a1b2c3d4e5f6g7h8i9j0"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "**Checkout fallback only.** The hosted Stripe Checkout URL — redirect the customer here to enter card details and complete payment. Omitted on the auto-charge path.",
            "example": "https://checkout.stripe.com/pay/cs_test_a1b2c3d4e5f6g7h8i9j0"
          }
        }
      },
      "CreditsSessionErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message.",
            "example": "credits must be a positive integer"
          }
        }
      },
      "SubscriptionSessionErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message.",
            "example": "successUrl is required"
          }
        }
      },
      "ClaimSubscriptionRequest": {
        "type": "object",
        "required": [
          "session_id"
        ],
        "properties": {
          "session_id": {
            "type": "string",
            "description": "The Stripe Checkout session id from the `session_id` query parameter on the success URL.",
            "example": "cs_live_a1b2c3d4e5f6g7h8i9j0"
          }
        }
      },
      "ClaimSubscriptionResponse": {
        "type": "object",
        "required": [
          "status",
          "subscription_id",
          "plan"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ]
          },
          "subscription_id": {
            "type": "string",
            "description": "The Stripe subscription now attached to the authenticated account.",
            "example": "sub_1Rz0abc123"
          },
          "plan": {
            "type": "string",
            "enum": [
              "starter",
              "pro"
            ],
            "description": "The plan the subscription is on, resolved from its Stripe price.",
            "example": "pro"
          }
        }
      },
      "ClaimSubscriptionErrorResponse": {
        "type": "object",
        "required": [
          "status",
          "error"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "error"
            ]
          },
          "error": {
            "type": "string",
            "description": "Machine-readable code (`session_not_found`, `already_claimed`, `no_subscription`) or a validation message.",
            "example": "already_claimed"
          }
        }
      },
      "SubscriptionPortalErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message.",
            "example": "returnUrl is required"
          }
        }
      },
      "CreateSubscriptionPortalRequest": {
        "type": "object",
        "required": [
          "returnUrl"
        ],
        "description": "Request body for creating a billing portal session. The account is taken from the `id` path parameter and must be accessible to the authenticated caller.",
        "properties": {
          "returnUrl": {
            "type": "string",
            "format": "uri",
            "description": "The URL to redirect to when the customer leaves the portal.",
            "example": "https://chat.recoupable.com/settings/billing"
          }
        }
      },
      "CreateSubscriptionPortalResponse": {
        "type": "object",
        "required": [
          "id",
          "url"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The portal session ID.",
            "example": "portal_sess_a1b2c3d4"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "The hosted portal URL. Redirect to this URL so the customer can manage their subscription.",
            "example": "https://billing.example.com/manage/portal_sess_a1b2c3d4"
          }
        }
      },
      "AdminCodingSlackQueryError": {
        "type": "object",
        "required": [
          "status",
          "error"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "error"
            ]
          },
          "error": {
            "type": "string",
            "description": "The first invalid query field or authentication-mechanism error."
          }
        }
      },
      "AdminCodingSlackAuthenticationError": {
        "description": "Missing or simultaneous authentication mechanisms return status/error. An invalid API key or Bearer credential returns status/message. Supply exactly one mechanism and authenticate a Recoup admin account.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/AdminCodingSlackQueryError"
          },
          {
            "$ref": "#/components/schemas/AccountErrorResponse"
          }
        ]
      },
      "AdminCodingSlackAuthorsResponse": {
        "type": "object",
        "required": [
          "status",
          "total",
          "tags"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ]
          },
          "total": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of distinct author IDs in the collected data."
          },
          "tags": {
            "type": "array",
            "description": "Distinct authors, deduplicated by ID and sorted by display name with the server localeCompare order. The first collected profile is retained; equal names do not merge distinct IDs.",
            "items": {
              "type": "object",
              "required": [
                "id",
                "name",
                "avatar"
              ],
              "properties": {
                "id": {
                  "type": "string",
                  "description": "Slack author ID; use it as the analytics tag filter."
                },
                "name": {
                  "type": "string",
                  "description": "Display name from the first collected profile."
                },
                "avatar": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Avatar URL from the first collected profile, or null."
                }
              }
            }
          }
        }
      },
      "AdminAgentKeyMetadata": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "name",
          "email",
          "created_at"
        ],
        "description": "One returned API-key record and the first matching current associated email. No credential value or hash is selected or returned.",
        "properties": {
          "id": {
            "type": "string",
            "description": "API-key record ID, not an account ID or a credential."
          },
          "name": {
            "type": "string",
            "description": "Stored name of this API-key record."
          },
          "email": {
            "type": "string",
            "description": "First current associated email matching the case-insensitive agent+ prefix; not necessarily a primary or canonical email."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Creation time of the API-key record, not the account or email."
          }
        }
      },
      "AdminAgentKeyMetadataResponse": {
        "type": "object",
        "required": [
          "status",
          "total",
          "signups"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ]
          },
          "total": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of key records in this returned signups array. Not a separate database-wide count or a count of unique accounts, agents, active keys or adoption."
          },
          "signups": {
            "type": "array",
            "description": "Returned metadata rows ordered by key-record created_at descending. The retained wire name does not establish signup origin. Multiple keys for one account remain separate rows.",
            "items": {
              "$ref": "#/components/schemas/AdminAgentKeyMetadata"
            }
          }
        }
      }
    }
  }
}