# Recipe: sites and sitemaps > Create a site (session only), move an article onto it and read its public sitemap. An article belongs to one site. A site has a `key` (a slug used in URLs) and a `base_url` (the public address its pages are served from). ## 1. List the sites ```sh curl "{{BASE_URL}}/v1/site/" \ -H "Authorization: Bearer $RENEWCMS_API_KEY" ``` ```json [{"id":1,"name":"Default","key":"default","base_url":"http://localhost:18080","default_social_image_id":null,"default_robots":"index","locale":null,"is_default":true,"article_count":0,"site_name":"","title_template":"%title% | %site%","default_description":""}] ``` ## 2. Create a site: not with a key Creating, editing, defaulting and deleting a site need a browser session from the owner. A key answers `403`: ```sh curl -X POST "{{BASE_URL}}/v1/site/" \ -H "Authorization: Bearer $RENEWCMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"x","key":"x","base_url":"https://x.example"}' ``` ``` HTTP/1.1 403 Forbidden This action needs a real session. ``` Ask the owner to create the site in the app, or send the request with the owner's `jwt` cookie. With a session the same request answers `201`: ```json {"id":2,"name":"Renew blog","key":"renew-blog","base_url":"https://blog.renew.example","default_social_image_id":null,"default_robots":"index","locale":null,"is_default":false,"article_count":0,"site_name":"","title_template":"%title% | %site%","default_description":""} ``` ## 3. Put an article on the site Use the site `id` as `site_id`: ```sh curl -X PATCH "{{BASE_URL}}/v1/article/1" \ -H "Authorization: Bearer $RENEWCMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"site_id":2}' ``` ## 4. Read the sitemap The sitemap is public and lists the online articles of one site, by its `key`: ```sh curl "{{BASE_URL}}/v1/site/renew-blog/sitemap" ``` ```json [{"url":"https://blog.renew.example/how-we-price-a-bathroom-renovation","modified_at":"2026-10-22T23:11:24Z","noindex":false}] ``` `url` is the site's `base_url` plus the article slug. Drafts are not listed. The response header `X-Total-Count` holds the number of entries. Page with `page` and `size` (`25`, `50`, `100` or `500`, default `100`); any other `size` answers `400`. An unknown key answers `404` with `site_not_found`. List only one site's articles with `GET /v1/article/?site=renew-blog`.