{
  "openapi": "3.1.0",
  "info": {
    "title": "Slew External Licenses Partner Protocol",
    "version": "1.0.0",
    "description": "Implement these endpoints on your own application server. Slew makes authenticated server-to-server HTTP requests. No SDK, Slew database access, or Slew runtime imports are required. Plan revisions and issued purchase identities are immutable; access revisions are monotonic. Retain purchase records and tombstones indefinitely."
  },
  "servers": [
    {
      "url": "https://your-app.example",
      "description": "Replace with your application server base URL"
    }
  ],
  "paths": {
    "/plans": {
      "get": {
        "summary": "Read available immutable plans; no price authority",
        "security": [
          {
            "partnerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "X-Slew-Mode",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "test",
                "live"
              ]
            },
            "description": "Selects an isolated test or live namespace. Request-body mode must match this header. A live-capable credential also authorizes test self-checks; a test-only credential never authorizes live. Test requests never grant live access."
          }
        ],
        "responses": {
          "200": {
            "description": "Persisted result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Plans"
                }
              }
            }
          },
          "400": {
            "description": "Invalid mode or request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credential",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid request schema",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Temporary provider failure; retry with the same purchase identity",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/licenses": {
      "post": {
        "summary": "Issue once per mode and purchase; repeat forever returns the same code",
        "security": [
          {
            "partnerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "X-Slew-Mode",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "test",
                "live"
              ]
            },
            "description": "Selects an isolated test or live namespace. Request-body mode must match this header. A live-capable credential also authorizes test self-checks; a test-only credential never authorizes live. Test requests never grant live access."
          }
        ],
        "responses": {
          "200": {
            "description": "Persisted result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/License"
                }
              }
            }
          },
          "400": {
            "description": "Invalid mode or request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credential",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid request schema",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Temporary provider failure; retry with the same purchase identity",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Immutable purchase identity or plan revision conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IssueLicense"
              }
            }
          }
        }
      }
    },
    "/licenses/by-purchase/{purchase_id}": {
      "get": {
        "summary": "Recover a persisted issue result after a lost response",
        "security": [
          {
            "partnerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "X-Slew-Mode",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "test",
                "live"
              ]
            },
            "description": "Selects an isolated test or live namespace. Request-body mode must match this header. A live-capable credential also authorizes test self-checks; a test-only credential never authorizes live. Test requests never grant live access."
          },
          {
            "name": "purchase_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Persisted result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/License"
                }
              }
            }
          },
          "400": {
            "description": "Invalid mode or request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credential",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid request schema",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Temporary provider failure; retry with the same purchase identity",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "License has not been issued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/licenses/by-purchase/{purchase_id}/access": {
      "put": {
        "summary": "Persist latest access state, including before issuance",
        "security": [
          {
            "partnerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "X-Slew-Mode",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "test",
                "live"
              ]
            },
            "description": "Selects an isolated test or live namespace. Request-body mode must match this header. A live-capable credential also authorizes test self-checks; a test-only credential never authorizes live. Test requests never grant live access."
          },
          {
            "name": "purchase_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Persisted result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccessReceipt"
                }
              }
            }
          },
          "400": {
            "description": "Invalid mode or request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credential",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid request schema",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Temporary provider failure; retry with the same purchase identity",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Fingerprint or same-revision state conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AccessUpdate"
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "partnerBearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "One server-only credential per connection. A live-capable credential authorizes live and isolated test requests so Slew can self-test it without a second secret. An optional test-only credential must never authorize live. Requested X-Slew-Mode selects all data and entitlements."
      }
    },
    "schemas": {
      "DesiredAccess": {
        "type": "object",
        "properties": {
          "state": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "revoked"
            ]
          },
          "revision": {
            "type": "integer",
            "minimum": 0,
            "maximum": 2147483647
          }
        },
        "required": [
          "state",
          "revision"
        ],
        "additionalProperties": false
      },
      "IssueLicense": {
        "type": "object",
        "properties": {
          "protocol_version": {
            "const": "1",
            "type": "string"
          },
          "purchase_id": {
            "type": "string",
            "minLength": 1
          },
          "customer_reference": {
            "type": "string",
            "minLength": 1,
            "description": "Opaque Slew principal identifier. Never an email address."
          },
          "mode": {
            "type": "string",
            "enum": [
              "test",
              "live"
            ]
          },
          "plan_id": {
            "type": "string",
            "minLength": 1
          },
          "plan_revision": {
            "type": "string",
            "minLength": 1
          },
          "input_fingerprint": {
            "type": "string",
            "minLength": 1,
            "description": "Opaque immutable fingerprint binding purchase_id, customer_reference, mode, plan_id and plan_revision. Persist and compare exactly."
          },
          "desired_access": {
            "$ref": "#/components/schemas/DesiredAccess"
          }
        },
        "required": [
          "protocol_version",
          "purchase_id",
          "customer_reference",
          "mode",
          "plan_id",
          "plan_revision",
          "input_fingerprint",
          "desired_access"
        ],
        "additionalProperties": false
      },
      "License": {
        "type": "object",
        "properties": {
          "license_id": {
            "type": "string",
            "minLength": 1
          },
          "purchase_id": {
            "type": "string",
            "minLength": 1
          },
          "mode": {
            "type": "string",
            "enum": [
              "test",
              "live"
            ]
          },
          "plan_id": {
            "type": "string",
            "minLength": 1
          },
          "plan_revision": {
            "type": "string",
            "minLength": 1
          },
          "input_fingerprint": {
            "type": "string",
            "minLength": 1
          },
          "license_code": {
            "type": "string",
            "minLength": 1
          },
          "activation_state": {
            "type": "string",
            "enum": [
              "unactivated",
              "activated"
            ]
          },
          "access_state": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "revoked"
            ]
          },
          "access_revision": {
            "type": "integer",
            "minimum": 0,
            "maximum": 2147483647
          },
          "issued_at": {
            "type": "string",
            "format": "date-time"
          },
          "activated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "license_id",
          "purchase_id",
          "mode",
          "plan_id",
          "plan_revision",
          "input_fingerprint",
          "license_code",
          "activation_state",
          "access_state",
          "access_revision",
          "issued_at",
          "activated_at",
          "expires_at"
        ],
        "additionalProperties": false
      },
      "AccessUpdate": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "test",
              "live"
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "revoked"
            ]
          },
          "revision": {
            "type": "integer",
            "minimum": 0,
            "maximum": 2147483647
          },
          "input_fingerprint": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "mode",
          "state",
          "revision",
          "input_fingerprint"
        ],
        "additionalProperties": false
      },
      "AccessReceipt": {
        "type": "object",
        "properties": {
          "purchase_id": {
            "type": "string",
            "minLength": 1
          },
          "mode": {
            "type": "string",
            "enum": [
              "test",
              "live"
            ]
          },
          "access_state": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "revoked"
            ]
          },
          "access_revision": {
            "type": "integer",
            "minimum": 0,
            "maximum": 2147483647
          }
        },
        "required": [
          "purchase_id",
          "mode",
          "access_state",
          "access_revision"
        ],
        "additionalProperties": false
      },
      "Plan": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "minLength": 1
          },
          "revision": {
            "type": "string",
            "minLength": 1
          },
          "name": {
            "type": "string",
            "minLength": 1
          },
          "features": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "term": {
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "kind": {
                    "const": "lifetime",
                    "type": "string"
                  },
                  "starts_at": {
                    "const": "activation",
                    "type": "string"
                  }
                },
                "required": [
                  "kind",
                  "starts_at"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "kind": {
                    "const": "fixed_duration",
                    "type": "string"
                  },
                  "duration_seconds": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "starts_at": {
                    "const": "activation",
                    "type": "string"
                  }
                },
                "required": [
                  "kind",
                  "duration_seconds",
                  "starts_at"
                ],
                "additionalProperties": false
              }
            ]
          },
          "redemption_url": {
            "type": "string",
            "format": "uri"
          },
          "redemption_instructions": {
            "type": "string",
            "minLength": 1
          },
          "available": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "revision",
          "name",
          "features",
          "term",
          "redemption_url",
          "redemption_instructions",
          "available"
        ],
        "additionalProperties": false
      },
      "Plans": {
        "type": "object",
        "properties": {
          "protocol_version": {
            "const": "1",
            "type": "string"
          },
          "integration_id": {
            "type": "string",
            "minLength": 1
          },
          "app_name": {
            "type": "string",
            "minLength": 1
          },
          "plans": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Plan"
            }
          }
        },
        "required": [
          "protocol_version",
          "integration_id",
          "app_name",
          "plans"
        ],
        "additionalProperties": false
      },
      "Error": {
        "type": "object",
        "properties": {
          "detail": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            ]
          }
        },
        "required": [
          "detail"
        ],
        "additionalProperties": false
      }
    }
  }
}
