{
  "openapi": "3.0.0",
  "info": {
    "title": "Propper Organization API",
    "version": "1.0.0",
    "description": "Organization-scoped management API for the Propper platform.\n\n## Base URL\n\n- **Production:** `https://api.propper.ai/v1/org`\n\n## Authentication\n\nOAuth 2.0 Bearer token. The organization is resolved from the token, not a path parameter:\n\n```\nAuthorization: Bearer <access_token>\n```\n\n## OAuth Scopes\n\n| Scope | Description |\n|-------|-------------|\n| `org:read` | Read organization data (profile and membership) |\n\nThe entitlement verdict projection (`view=salesforce`) is platform-only: it is\ncallable exclusively by Propper-generated Salesforce client applications and is\nnot reachable with any customer-requestable scope."
  },
  "servers": [
    {
      "url": "https://api.propper.ai",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Entitlements",
      "description": "The organization's derived entitlement verdict"
    }
  ],
  "paths": {
    "/v1/org/entitlements": {
      "get": {
        "operationId": "getOrgEntitlements",
        "summary": "Resolve the organization entitlement verdict",
        "description": "Returns the calling organization's derived entitlement verdict for the requested view. The organization is taken from the access token. The salesforce view is platform-only: callable exclusively by Propper-generated Salesforce client applications, not by customer-created ones.",
        "tags": [
          "Entitlements"
        ],
        "parameters": [
          {
            "name": "view",
            "in": "query",
            "required": true,
            "description": "The projection to return. Currently only `salesforce` is supported.",
            "schema": {
              "type": "string",
              "enum": [
                "salesforce"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The resolved entitlement verdict. An organization without an active connector still returns 200 (with `gateState: no_connector`); the endpoint reports entitlement and is never itself entitlement-gated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EntitlementResolution"
                }
              }
            }
          },
          "400": {
            "description": "The `view` query parameter is missing or unsupported."
          },
          "401": {
            "description": "Missing or invalid access token."
          },
          "403": {
            "description": "The token is not a platform client authorized for the entitlement verdict projection."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    },
    "schemas": {
      "EntitlementResolution": {
        "type": "object",
        "description": "The derived entitlement verdict for one organization and view.",
        "properties": {
          "resolvedAt": {
            "type": "string",
            "format": "date-time"
          },
          "org": {
            "type": "object",
            "properties": {
              "propperOrgId": {
                "type": "string"
              },
              "salesforceOrgId": {
                "type": "string",
                "nullable": true
              },
              "isSandbox": {
                "type": "boolean"
              }
            }
          },
          "connector": {
            "type": "object",
            "properties": {
              "active": {
                "type": "boolean"
              },
              "tier": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "dependency": {
            "type": "object",
            "properties": {
              "satisfied": {
                "type": "boolean"
              },
              "required": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "missing": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          "gen": {
            "type": "object",
            "properties": {
              "active": {
                "type": "boolean"
              }
            }
          },
          "trial": {
            "type": "object",
            "properties": {
              "active": {
                "type": "boolean"
              },
              "expiresAt": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              }
            }
          },
          "gateState": {
            "type": "string",
            "description": "The verdict state. The service emits `no_sign_gen`, `no_connector`, or `operational`; `no_link` is decided by the integration client and is never emitted by the server.",
            "enum": [
              "no_sign_gen",
              "no_connector",
              "operational"
            ]
          },
          "bonusTxn": {
            "type": "object",
            "nullable": true,
            "properties": {
              "limit": {
                "type": "integer",
                "nullable": true
              },
              "used": {
                "type": "integer"
              },
              "remaining": {
                "type": "integer",
                "nullable": true
              },
              "expiresAt": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              }
            }
          },
          "onboarding": {
            "type": "object",
            "nullable": true,
            "properties": {
              "state": {
                "type": "string"
              },
              "expiresAt": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              }
            }
          },
          "graceTtlSeconds": {
            "type": "integer"
          },
          "links": {
            "type": "object",
            "properties": {
              "manageBilling": {
                "type": "string",
                "nullable": true
              },
              "contactSales": {
                "type": "string",
                "nullable": true
              }
            }
          }
        }
      }
    }
  }
}