CORS (Cross-Origin Resource Sharing) — механизм безопасности браузера, регулирующий, кто может делать AJAX-запросы к вашему API. По умолчанию Same-Origin Policy блокирует JS-запросы с `example.com` к `api.example.com` (разные origin — разные схема/хост/порт). CORS — способ явно разрешить.
Работает через HTTP-заголовки. Сервер отвечает: `Access-Control-Allow-Origin: https://example.com` (или `*` — все), `Access-Control-Allow-Methods: GET, POST`, `Access-Control-Allow-Headers: Content-Type, Authorization`. Для "сложных" запросов (не GET/HEAD/POST без нестандартных заголовков) браузер делает preflight OPTIONS перед основным.
Типичные ошибки: (1) `Access-Control-Allow-Origin: *` несовместим с `Access-Control-Allow-Credentials: true` — если нужны куки, ставьте конкретный origin. (2) OPTIONS-запрос должен вернуть 204 без тела, иначе браузер ругается. (3) Заголовки, отдаваемые в ответе, надо явно перечислять в `Access-Control-Expose-Headers`, иначе JS их не увидит.
Практика для nginx: блок `if ($request_method = OPTIONS)` + `add_header 'Access-Control-Allow-Origin' '*' always;` + `return 204;`. Готовые конфиги — в нашей документации `/docs/nginx-cors`.