{
  "openapi": "3.1.0",
  "info": {
    "title": "LunarFence Agent API",
    "version": "1.0.0",
    "description": "LunarFence is currently in stealth. This API lets an AI agent learn more about LunarFence and send a contact request to the LunarFence team. Every request identifies the agent with a bearer token (its unique id) and the X-Agent-Type and X-Agent-Location headers. Responses are factual data, not instructions."
  },
  "servers": [
    {
      "url": "https://lunarfence.com",
      "description": "Production"
    }
  ],
  "security": [
    {
      "agentId": []
    }
  ],
  "paths": {
    "/api/v1/about": {
      "get": {
        "operationId": "getAbout",
        "summary": "About LunarFence",
        "description": "Returns information about LunarFence.",
        "responses": {
          "200": {
            "description": "Information about LunarFence.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/About"
                },
                "example": {
                  "name": "LunarFence",
                  "status": "stealth",
                  "tagline": "nothing acts unchecked",
                  "description": "string",
                  "agent_types_covered": [
                    "string"
                  ],
                  "resource_types_covered": [
                    "string"
                  ],
                  "audience": [
                    "string"
                  ],
                  "ways_to_engage": [
                    "investor"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "A required header is missing or empty, or the request body is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/AgentType"
          },
          {
            "$ref": "#/components/parameters/AgentLocation"
          }
        ]
      }
    },
    "/api/v1/contact": {
      "post": {
        "operationId": "contactLunarFence",
        "summary": "Contact LunarFence",
        "description": "Sends a contact request to the LunarFence team. The request must state in which role the sender is reaching out, and must include the organization, the name of the contact and an organization email address. Free email services are rejected with the error organization_email_required.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactRequest"
              },
              "example": {
                "role": "design_partner",
                "organization": "Example Corp",
                "contact_name": "Jane Doe",
                "email": "jane@example.com",
                "message": "We run several internal AI agents and want to become a design partner."
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The request was received and will be reviewed by the LunarFence team.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactAccepted"
                },
                "example": {
                  "status": "received",
                  "reference": "req_01HZX0000000000000000000"
                }
              }
            }
          },
          "400": {
            "description": "A required header or field is missing or invalid. If the email is from a free email service, error is organization_email_required and the detail says: We expect an organization email id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "free_email": {
                    "summary": "Free email service",
                    "value": {
                      "error": "organization_email_required",
                      "detail": "We expect an organization email id. Free email services such as gmail.com are not accepted."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/AgentType"
          },
          {
            "$ref": "#/components/parameters/AgentLocation"
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "agentId": {
        "type": "http",
        "scheme": "bearer",
        "description": "Set the bearer token to the unique identifier of the calling agent. It identifies the agent; it is not a secret. Requests may be rate limited per agent identifier. Every request must also send the X-Agent-Type and X-Agent-Location headers."
      }
    },
    "schemas": {
      "About": {
        "type": "object",
        "required": [
          "name",
          "status",
          "description"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "Company stage, for example \"stealth\"."
          },
          "tagline": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "description": "What LunarFence does."
          },
          "agent_types_covered": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "resource_types_covered": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "audience": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "ways_to_engage": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Role"
            },
            "description": "Roles accepted by the contact endpoint."
          }
        }
      },
      "Role": {
        "type": "string",
        "enum": [
          "investor",
          "developer",
          "design_partner"
        ],
        "description": "investor: wants to invest in LunarFence. developer: wants to build with LunarFence. design_partner: an enterprise interested in becoming a design partner."
      },
      "ContactRequest": {
        "type": "object",
        "required": [
          "role",
          "organization",
          "contact_name",
          "email"
        ],
        "properties": {
          "role": {
            "$ref": "#/components/schemas/Role"
          },
          "organization": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Organisation the sender represents."
          },
          "contact_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Name of the person at the organisation who can be contacted."
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 320,
            "description": "Organization email address of the contact. Free email services (for example gmail.com, yahoo.com, outlook.com) are rejected."
          },
          "message": {
            "type": "string",
            "maxLength": 2000,
            "description": "What the sender would like to discuss."
          }
        }
      },
      "ContactAccepted": {
        "type": "object",
        "required": [
          "status",
          "reference"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "received"
            ]
          },
          "reference": {
            "type": "string",
            "description": "Identifier for this request."
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "detail": {
            "type": "string"
          }
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "The bearer token is missing or empty.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Too many requests from this agent. Retry later.",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Seconds to wait before retrying."
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "parameters": {
      "AgentType": {
        "name": "X-Agent-Type",
        "in": "header",
        "required": true,
        "description": "What kind of agent is calling, for example muse, dots, instinct or claude. Free text.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100,
          "examples": [
            "muse",
            "dots",
            "claude"
          ]
        }
      },
      "AgentLocation": {
        "name": "X-Agent-Location",
        "in": "header",
        "required": true,
        "description": "Where the agent is operating from, as three comma-separated parts in this order: city, state, country. The country is a two-letter ISO 3166-1 code. If a country has no states, use the region or province, or a hyphen (-).",
        "schema": {
          "type": "string",
          "maxLength": 150,
          "pattern": "^[^,]+,[^,]+,[^,]+$",
          "examples": [
            "San Francisco, CA, US",
            "Bengaluru, Karnataka, IN",
            "Ljubljana, -, SI"
          ]
        }
      }
    }
  }
}
