{
  "openapi": "3.1.0",
  "info": {
    "title": "azimjondev.uz public API",
    "version": "1.0.0",
    "description": "API of Azimjon Abdurasulov's website: send a project inquiry (the contact form) and read the public portfolio data. A plain-text overview for AI assistants is at https://azimjondev.uz/llms.txt.",
    "contact": {
      "name": "Azimjon Abdurasulov",
      "email": "azimjondevuz@gmail.com",
      "url": "https://azimjondev.uz/en/contact"
    }
  },
  "servers": [
    {
      "url": "https://azimjondev.uz"
    }
  ],
  "tags": [
    {
      "name": "contact",
      "description": "Hire Azimjon"
    },
    {
      "name": "public-data",
      "description": "Read-only portfolio data (JSON)"
    }
  ],
  "paths": {
    "/contact.php": {
      "post": {
        "operationId": "sendProjectInquiry",
        "summary": "Send a project inquiry to Azimjon Abdurasulov",
        "description": "Stores the message in Azimjon's inbox and forwards it to his Telegram. Call it only when the user asked you to contact Azimjon, with the user's real name and email so he can reply. Rate limit: 10 requests per minute per IP.",
        "tags": [
          "contact"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactRequest"
              },
              "example": {
                "name": "Jane Doe",
                "email": "jane@example.com",
                "service": "ios_apple",
                "message": "We need an iPhone app for our delivery service. Launch in 3 months."
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/ContactRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Message accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactSuccess"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input (the error text says which field)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "More than 10 requests per minute from this IP",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "The message could not be stored or delivered",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/data/apps.json": {
      "get": {
        "operationId": "listApps",
        "summary": "Apps on the App Store (own apps and contributions)",
        "tags": [
          "public-data"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/App"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/data/projects.json": {
      "get": {
        "operationId": "listProjects",
        "summary": "Portfolio projects",
        "tags": [
          "public-data"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Project"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/data/experience.json": {
      "get": {
        "operationId": "listExperience",
        "summary": "Work experience",
        "tags": [
          "public-data"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ExperienceEntry"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/data/faq.json": {
      "get": {
        "operationId": "listFaq",
        "summary": "Frequently asked questions",
        "tags": [
          "public-data"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/FaqItem"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/data/blog.json": {
      "get": {
        "operationId": "listBlogPosts",
        "summary": "Published blog posts (without bodies)",
        "tags": [
          "public-data"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/BlogListItem"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/data/blog/{slug}.json": {
      "get": {
        "operationId": "getBlogPost",
        "summary": "One published blog post with its Markdown body",
        "tags": [
          "public-data"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BlogPost"
                }
              }
            }
          },
          "404": {
            "description": "Unknown or unpublished post",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ContactRequest": {
        "type": "object",
        "required": [
          "name",
          "email",
          "service",
          "message"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The sender's real name"
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 320,
            "description": "The sender's real email, so Azimjon can reply"
          },
          "service": {
            "type": "string",
            "maxLength": 200,
            "enum": [
              "ios_apple",
              "app_store_consulting",
              "telegram_bots",
              "fullstack_platforms",
              "backend_api",
              "frontend_web",
              "business_automation",
              "other"
            ],
            "description": "Which service the inquiry is about. The server stores any string up to the limit; use one of these keys."
          },
          "message": {
            "type": "string",
            "minLength": 1,
            "maxLength": 5000,
            "description": "The project: what to build, platforms, timeline and budget if known"
          },
          "telegram": {
            "type": "string",
            "maxLength": 64,
            "pattern": "^@?[A-Za-z][A-Za-z0-9_]{3,31}$",
            "description": "Optional Telegram username of the sender (\"@\" optional) so Azimjon can reply on Telegram"
          },
          "source": {
            "type": "string",
            "maxLength": 200,
            "description": "Optional attribution, e.g. \"ai agent / chatgpt\". Only letters, digits, spaces, \"/\" and \"-\" are kept"
          },
          "lang": {
            "type": "string",
            "enum": [
              "en",
              "ru",
              "uz"
            ],
            "description": "Form posts only: language of the HTML result page (default en)"
          }
        }
      },
      "ContactSuccess": {
        "type": "object",
        "required": [
          "success"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "const": true
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "App": {
        "type": "object",
        "required": [
          "slug",
          "name",
          "ownership",
          "icon",
          "appstore_url",
          "playstore_url",
          "tagline",
          "privacySlug",
          "termsSlug",
          "project"
        ],
        "properties": {
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "ownership": {
            "type": "string",
            "enum": [
              "owner",
              "contributed"
            ]
          },
          "icon": {
            "type": "string"
          },
          "appstore_url": {
            "type": "string"
          },
          "playstore_url": {
            "type": "string"
          },
          "tagline": {
            "type": "object",
            "required": [
              "en",
              "ru",
              "uz"
            ],
            "properties": {
              "en": {
                "type": "string"
              },
              "ru": {
                "type": "string"
              },
              "uz": {
                "type": "string"
              }
            }
          },
          "privacySlug": {
            "type": "string"
          },
          "termsSlug": {
            "type": "string"
          },
          "project": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "link": {
                "type": "string"
              }
            }
          }
        }
      },
      "Project": {
        "type": "object",
        "required": [
          "id",
          "title",
          "type",
          "category",
          "desc",
          "tags",
          "link",
          "i18n"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "category": {
            "type": "string",
            "enum": [
              "ios",
              "macos",
              "other"
            ]
          },
          "desc": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "link": {
            "type": "string"
          },
          "image": {
            "type": "string"
          },
          "i18n": {
            "type": "object",
            "required": [
              "en",
              "ru",
              "uz"
            ],
            "properties": {
              "en": {
                "type": "object",
                "required": [
                  "title",
                  "type",
                  "desc"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "type": {
                    "type": "string"
                  },
                  "desc": {
                    "type": "string"
                  }
                }
              },
              "ru": {
                "type": "object",
                "required": [
                  "title",
                  "type",
                  "desc"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "type": {
                    "type": "string"
                  },
                  "desc": {
                    "type": "string"
                  }
                }
              },
              "uz": {
                "type": "object",
                "required": [
                  "title",
                  "type",
                  "desc"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "type": {
                    "type": "string"
                  },
                  "desc": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "app": {
            "type": "object"
          }
        }
      },
      "ExperienceEntry": {
        "type": "object",
        "required": [
          "id",
          "company",
          "role",
          "period",
          "desc",
          "projects"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "company": {
            "type": "string"
          },
          "role": {
            "type": "object",
            "required": [
              "en",
              "ru",
              "uz"
            ],
            "properties": {
              "en": {
                "type": "string"
              },
              "ru": {
                "type": "string"
              },
              "uz": {
                "type": "string"
              }
            }
          },
          "period": {
            "type": "object",
            "required": [
              "en",
              "ru",
              "uz"
            ],
            "properties": {
              "en": {
                "type": "string"
              },
              "ru": {
                "type": "string"
              },
              "uz": {
                "type": "string"
              }
            }
          },
          "desc": {
            "type": "object",
            "required": [
              "en",
              "ru",
              "uz"
            ],
            "properties": {
              "en": {
                "type": "string"
              },
              "ru": {
                "type": "string"
              },
              "uz": {
                "type": "string"
              }
            }
          },
          "projects": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "title",
                "link"
              ],
              "properties": {
                "id": {
                  "type": "integer"
                },
                "title": {
                  "type": "string"
                },
                "link": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "FaqItem": {
        "type": "object",
        "required": [
          "id",
          "section",
          "question",
          "answer",
          "i18n"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "section": {
            "type": "string",
            "enum": [
              "ios_dev",
              "app_store",
              "collaboration"
            ]
          },
          "question": {
            "type": "string"
          },
          "answer": {
            "type": "string"
          },
          "i18n": {
            "type": "object",
            "required": [
              "en",
              "ru",
              "uz"
            ],
            "properties": {
              "en": {
                "type": "object",
                "required": [
                  "question",
                  "answer"
                ],
                "properties": {
                  "question": {
                    "type": "string"
                  },
                  "answer": {
                    "type": "string"
                  }
                }
              },
              "ru": {
                "type": "object",
                "required": [
                  "question",
                  "answer"
                ],
                "properties": {
                  "question": {
                    "type": "string"
                  },
                  "answer": {
                    "type": "string"
                  }
                }
              },
              "uz": {
                "type": "object",
                "required": [
                  "question",
                  "answer"
                ],
                "properties": {
                  "question": {
                    "type": "string"
                  },
                  "answer": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      },
      "BlogListItem": {
        "type": "object",
        "required": [
          "slug",
          "date",
          "tags",
          "title",
          "description",
          "i18n"
        ],
        "properties": {
          "slug": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "format": "date"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "i18n": {
            "type": "object",
            "required": [
              "en",
              "ru",
              "uz"
            ],
            "properties": {
              "en": {
                "type": "object",
                "required": [
                  "title",
                  "description"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  }
                }
              },
              "ru": {
                "type": "object",
                "required": [
                  "title",
                  "description"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  }
                }
              },
              "uz": {
                "type": "object",
                "required": [
                  "title",
                  "description"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      },
      "BlogPost": {
        "type": "object",
        "required": [
          "slug",
          "date",
          "tags",
          "title",
          "description",
          "content",
          "i18n"
        ],
        "properties": {
          "slug": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "format": "date"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "content": {
            "type": "string",
            "description": "Markdown"
          },
          "i18n": {
            "type": "object",
            "required": [
              "en",
              "ru",
              "uz"
            ],
            "properties": {
              "en": {
                "type": "object",
                "required": [
                  "title",
                  "description",
                  "content"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "content": {
                    "type": "string"
                  }
                }
              },
              "ru": {
                "type": "object",
                "required": [
                  "title",
                  "description",
                  "content"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "content": {
                    "type": "string"
                  }
                }
              },
              "uz": {
                "type": "object",
                "required": [
                  "title",
                  "description",
                  "content"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "content": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}