{
 "openapi": "3.1.0",
 "info": {
  "title": "Approval Rules",
  "version": "1.0.0",
  "description": "Rules for what your AI agent may do without asking. Small, reversible actions under your limits get auto-approved; everything else becomes a plain-English approval card you tap Approve or Reject on. Free watch-only mode logs what it would decide and drafts a weekly report; Pro at $9 a month makes the rules act. Free 200/day; Pro $9/month: https://pay.instaloops.com/b/28EcN57dCd797H190H83C3x"
 },
 "servers": [
  {
   "url": "https://approve.cloudforbots.com"
  }
 ],
 "components": {
  "securitySchemes": {
   "bearer": {
    "type": "http",
    "scheme": "bearer"
   }
  }
 },
 "paths": {
  "/api/run/check_action": {
   "post": {
    "operationId": "check_action",
    "summary": "Before a consequential action, ask whether the user's rules auto-approve it",
    "description": "Before a consequential action, ask whether the user's rules auto-approve it. Returns auto_approve, needs_approval (with a plain-English approval card and a link the user can tap) or deny. Free plan is watch-only: it reports what it WOULD decide and logs it for the weekly report, but nothing counts as approved, so ask your user as you normally would.",
    "security": [
     {},
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "action": {
          "type": "object",
          "description": "The action your agent wants to take.",
          "properties": {
           "type": {
            "type": "string",
            "description": "Short verb: read, search, draft, send_email, send_message, post, purchase, payment, delete, deploy, change_settings, ..."
           },
           "summary": {
            "type": "string",
            "description": "One plain sentence of what will happen, e.g. \"Buy a $3.99 domain renewal for example.com\"."
           },
           "amount_usd": {
            "type": "number",
            "description": "Money involved, if any."
           },
           "target": {
            "type": "string",
            "description": "Who or what it touches: a recipient email, domain, file, repo."
           },
           "reversible": {
            "type": "boolean",
            "description": "Can it be undone easily?"
           }
          },
          "required": [
           "type",
           "summary"
          ]
         }
        },
        "required": [
         "action"
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Result with job, understood, outcome, usage",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "401": {
      "description": "bad_agent_key"
     },
     "429": {
      "description": "free_limit_reached (includes upgrade link)"
     }
    }
   }
  },
  "/api/run/get_decision": {
   "post": {
    "operationId": "get_decision",
    "summary": "Check whether the user approved or rejected an approval card (by card_id and card_token)",
    "description": "Check whether the user approved or rejected an approval card (by card_id and card_token). Only act when status is approved.",
    "security": [
     {},
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "card_id": {
          "type": "string"
         },
         "card_token": {
          "type": "string"
         }
        },
        "required": [
         "card_id",
         "card_token"
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Result with job, understood, outcome, usage",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "401": {
      "description": "bad_agent_key"
     },
     "429": {
      "description": "free_limit_reached (includes upgrade link)"
     }
    }
   }
  },
  "/api/run/set_rules": {
   "post": {
    "operationId": "set_rules",
    "summary": "Save the user's rules (needs an API key so they stay yours)",
    "description": "Save the user's rules (needs an API key so they stay yours). Each rule: {name, when:{type:[...], max_usd, min_usd, reversible, target_ends_with:[...]}, verdict:\"auto\"|\"ask\"|\"deny\"}. First matching rule wins; anything unmatched needs approval. Call once without confirm to preview, then with confirm=true.",
    "security": [
     {},
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "rules": {
          "type": "array",
          "items": {
           "type": "object"
          }
         },
         "confirm": {
          "type": "boolean"
         }
        },
        "required": [
         "rules"
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Result with job, understood, outcome, usage",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "401": {
      "description": "bad_agent_key"
     },
     "429": {
      "description": "free_limit_reached (includes upgrade link)"
     }
    }
   }
  },
  "/api/run/get_rules": {
   "post": {
    "operationId": "get_rules",
    "summary": "Show the rules in effect for your key (or the default starter rules).",
    "description": "Show the rules in effect for your key (or the default starter rules).",
    "security": [
     {},
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {}
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Result with job, understood, outcome, usage",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "401": {
      "description": "bad_agent_key"
     },
     "429": {
      "description": "free_limit_reached (includes upgrade link)"
     }
    }
   }
  },
  "/api/run/weekly_report": {
   "post": {
    "operationId": "weekly_report",
    "summary": "Draft a plain-English report of the last 7 days: actions checked, how many your rules would auto-approve, how many needed you, top kinds of asks, and rule suggestions",
    "description": "Draft a plain-English report of the last 7 days: actions checked, how many your rules would auto-approve, how many needed you, top kinds of asks, and rule suggestions. Read-only; sends nothing.",
    "security": [
     {},
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {}
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Result with job, understood, outcome, usage",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "401": {
      "description": "bad_agent_key"
     },
     "429": {
      "description": "free_limit_reached (includes upgrade link)"
     }
    }
   }
  },
  "/api/key": {
   "post": {
    "operationId": "get_free_key",
    "summary": "Get a free API key",
    "responses": {
     "200": {
      "description": "api_key"
     }
    }
   }
  }
 }
}