{
  "openapi": "3.0.3",
  "info": {
    "title": "RunPR API and MCP reference",
    "version": "1.0.0",
    "description": "A documented starter subset of existing integrations, not an inventory of every internal route. REST reads and MCP require authentication. MCP organization API keys and organization service tokens are distinct credentials and are not interchangeable. Neither uses OAuth. Request access from RunPR support; no public anonymous customer-data access. Service-token x-scopes and x-required-scopes describe actual enforced permissions, not OAuth scopes.",
    "contact": {
      "name": "RunPR support",
      "url": "https://runpr.ai/docs"
    }
  },
  "servers": [
    {
      "url": "https://runpr.ai"
    }
  ],
  "externalDocs": {
    "url": "https://runpr.ai/docs"
  },
  "tags": [
    {
      "name": "Organization-key API"
    },
    {
      "name": "Service-token API"
    },
    {
      "name": "MCP"
    }
  ],
  "paths": {
    "/api/v1/events": {
      "get": {
        "operationId": "listEvents",
        "summary": "Read organization monitoring events",
        "tags": [
          "Organization-key API"
        ],
        "security": [
          {
            "OrganizationApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful read.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "events": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Event"
                      }
                    },
                    "count": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "events",
                    "count"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or ineligible credential.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error; response format is not guaranteed."
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Use a positive integer; values above 100 are capped. Malformed values are not reliably rejected with 400.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "sourceRef",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/monitors": {
      "get": {
        "operationId": "listMonitors",
        "summary": "Read organization monitors",
        "tags": [
          "Organization-key API"
        ],
        "security": [
          {
            "OrganizationApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful read.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "monitors": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Monitor"
                      }
                    }
                  },
                  "required": [
                    "monitors"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or ineligible credential.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error; response format is not guaranteed."
          }
        }
      }
    },
    "/api/v1/monitors/{id}": {
      "get": {
        "operationId": "getMonitor",
        "summary": "Read one organization monitor",
        "tags": [
          "Organization-key API"
        ],
        "security": [
          {
            "OrganizationApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful read.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "monitor": {
                      "$ref": "#/components/schemas/Monitor"
                    }
                  },
                  "required": [
                    "monitor"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or ineligible credential.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error; response format is not guaranteed."
          },
          "404": {
            "description": "Monitor not found in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/orgs/{orgId}/agent/status": {
      "get": {
        "operationId": "getAgentStatus",
        "summary": "Read organization agent heartbeat status",
        "tags": [
          "Service-token API"
        ],
        "security": [
          {
            "OrganizationServiceToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentStatus"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or ineligible credential.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error; response format is not guaranteed."
          },
          "403": {
            "description": "Token organization does not match the URL or config.read is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Organization not found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "ORG_NOT_FOUND"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "details": {
                          "type": "object"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "details"
                      ]
                    }
                  },
                  "required": [
                    "error"
                  ]
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "orgId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-required-scopes": [
          "config.read"
        ]
      }
    },
    "/api/mcp": {
      "post": {
        "operationId": "mcpRequest",
        "summary": "Call the authenticated RunPR MCP server",
        "description": "Streamable HTTP with JSON responses. Use an MCP SDK: initialize, notifications/initialized, tools/list, then tools/call. Organization API key required for every request. Seven tools; no send tool. Do not interpret HTTP 200 as tool success: inspect JSON-RPC error and tool result isError. Use live tools/list for current input schemas. GET returns 405; standalone SSE is not supported. Normal model/drafting quotas apply. Draft submissions may be held and never send automatically.",
        "tags": [
          "MCP"
        ],
        "security": [
          {
            "OrganizationApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "application/json, text/event-stream"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "jsonrpc": {
                    "type": "string",
                    "enum": [
                      "2.0"
                    ]
                  },
                  "id": {
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "integer"
                      }
                    ]
                  },
                  "method": {
                    "type": "string"
                  },
                  "params": {
                    "type": "object",
                    "additionalProperties": true
                  }
                },
                "required": [
                  "jsonrpc",
                  "method"
                ]
              },
              "example": {
                "jsonrpc": "2.0",
                "id": 1,
                "method": "initialize",
                "params": {
                  "protocolVersion": "2025-11-25",
                  "capabilities": {},
                  "clientInfo": {
                    "name": "your-agent",
                    "version": "1.0.0"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC result or error; tool results can contain isError.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jsonrpc": {
                      "type": "string"
                    },
                    "id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "nullable": true
                        },
                        {
                          "type": "integer"
                        }
                      ]
                    },
                    "result": {},
                    "error": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "Notification accepted; no response body."
          },
          "400": {
            "description": "Invalid JSON or protocol request; plain text or JSON-RPC error."
          },
          "401": {
            "description": "Invalid organization API key or no billing access.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jsonrpc": {
                      "type": "string"
                    },
                    "id": {
                      "anyOf": [
                        {
                          "type": "string",
                          "nullable": true
                        },
                        {
                          "type": "integer"
                        }
                      ]
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "integer"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "code",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "jsonrpc",
                    "id",
                    "error"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Product access disabled; plain-text response."
          },
          "406": {
            "description": "Accept header must include application/json and text/event-stream."
          },
          "413": {
            "description": "Request exceeds 128,000 bytes; plain-text response."
          },
          "415": {
            "description": "Unsupported content type."
          },
          "429": {
            "description": "Organization request limit reached; 60 requests per minute. JSON-RPC error.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retry."
              }
            }
          },
          "503": {
            "description": "Request quota service unavailable; plain-text response."
          },
          "500": {
            "description": "Unexpected server error; response format is not guaranteed."
          }
        },
        "externalDocs": {
          "url": "https://runpr.ai/skill.md"
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "OrganizationApiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "Organization API key",
        "description": "Support-provisioned organization key for MCP and /api/v1/events and monitors. Billing/access gates apply. Organization-wide, without per-tool scopes. Not an OCA service token or OAuth credential."
      },
      "OrganizationServiceToken": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "OCA service token",
        "description": "Owner/admin-provisioned, revocable service token. Organization must match the URL. Request only required scopes through the admin provisioning API; the current settings UI uses a broad fixed set. Not accepted by MCP. No OAuth flow.",
        "x-scopes": {
          "config.read": "Read organization configuration and agent status."
        }
      }
    },
    "schemas": {
      "Event": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "organizationId": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "eventType": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "workspaceId": {
            "type": "string",
            "nullable": true
          },
          "accountId": {
            "type": "string",
            "nullable": true
          },
          "sourceType": {
            "type": "string",
            "nullable": true
          },
          "sourceRef": {
            "type": "string",
            "nullable": true
          },
          "summary": {
            "type": "string",
            "nullable": true
          },
          "payload": {}
        },
        "required": [
          "id",
          "organizationId",
          "title",
          "eventType",
          "createdAt"
        ]
      },
      "Monitor": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "organizationId": {
            "type": "string"
          },
          "accountId": {
            "type": "string",
            "nullable": true
          },
          "name": {
            "type": "string"
          },
          "feedUrl": {
            "type": "string"
          },
          "keywords": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "isActive": {
            "type": "boolean"
          },
          "sourceMode": {
            "type": "string",
            "enum": [
              "feed",
              "sitemap",
              "scrape"
            ]
          },
          "siteUrl": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "organizationId",
          "name",
          "feedUrl",
          "keywords",
          "isActive",
          "sourceMode",
          "siteUrl",
          "createdAt",
          "updatedAt"
        ],
        "description": "Monitor record, including last-attempt and last-success diagnostics when available. Additional fields may be returned."
      },
      "AgentStatus": {
        "type": "object",
        "properties": {
          "lastSeenAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "runtimeUrl": {
            "type": "string",
            "nullable": true
          },
          "skillsEnabled": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "healthy": {
            "type": "boolean",
            "description": "True when the latest agent heartbeat is less than five minutes old."
          }
        },
        "required": [
          "lastSeenAt",
          "runtimeUrl",
          "skillsEnabled",
          "healthy"
        ]
      }
    }
  }
}
