# Your first published article

Five requests. Create a key, create a draft, publish it, read it back, and read it the way a browser would.

## Get a key

Keys are created in the dashboard, not through this API, because creating the first one needs a signed in person rather than a credential you do not have yet.

1. **Open Settings, then API keys** In the dashboard, go to Settings and choose API keys. You need the `api_keys.manage` permission; an owner or admin has it by default.
2. **Create a secret key** Choose **Secret** and give it the scopes this quickstart uses: `articles:read`, `articles:write` and `meta:read`. A key can never do more than the person who created it, so grant yourself what you need first.
3. **Copy it now** The secret is shown once and never again. Only a hash is stored, so a lost key can be rotated but not recovered.
4. **Create a publishable key too** Choose **Publishable** with `articles:read`. Step 5 uses it. This is the kind that is safe in a browser bundle.

> A secret key is a server side credential. Do not put one in a browser bundle, a mobile app, or a repository. If one leaks, revoke it from the same screen; revocation takes effect on the next request.

## Set your shell up

Every example on this page uses these two values. Export them once and the requests below are copy-pasteable as they stand.

shell:

```
export WRITAVO_SECRET_KEY="wv_sk_your_secret_key"
export WRITAVO_PUBLISHABLE_KEY="wv_pub_your_publishable_key"
export WRITAVO_BASE="https://api.writavo.com/v1"
```

The snippets print the key inline so that each one is complete on its own. Substitute your real key, or replace the literal with `$WRITAVO_SECRET_KEY`.

## The five requests

**1. Check your key works** (returns 200)

```bash

curl https://api.writavo.com/v1/ping \
  -H "Authorization: Bearer wv_sk_EXAMPLE0000000000000000000000000000"

```

The cheapest authenticated call there is. It tells you the kind of key you presented and the scopes it carries.

**2. Create a draft** (returns 201)

```bash

curl -X POST https://api.writavo.com/v1/articles \
  -H "Authorization: Bearer wv_sk_EXAMPLE0000000000000000000000000000" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: b6f4b0e2-0000-4000-8000-0000000000aa" \
  -d '{
  "title": "How to choose a headless CMS",
  "slug": "how-to-choose-a-headless-cms",
  "excerpt": "A practical framework for picking a headless CMS without regretting it.",
  "content": "## Start with your delivery model\n\nThe first question is not which CMS. It is where the HTML is rendered."
}'

```

This always creates a draft. There is no request field that can make it public.

**3. Publish it** (returns 200)

```bash

curl -X POST https://api.writavo.com/v1/articles/3f1b0c7a-0000-4000-8000-000000000001/publish \
  -H "Authorization: Bearer wv_sk_EXAMPLE0000000000000000000000000000"

```

Publishing is free. It makes no external call, so it spends no credits and is unaffected by your spend cap.

**4. Read it back** (returns 200)

```bash

curl https://api.writavo.com/v1/articles/3f1b0c7a-0000-4000-8000-000000000001?fields=id,status,title,slug,published_at \
  -H "Authorization: Bearer wv_sk_EXAMPLE0000000000000000000000000000"

```

A sparse fieldset. `fields` is an allow list, so there is no way to ask for everything.

**5. Read it with a publishable key** (returns 200)

```bash

curl https://api.writavo.com/v1/articles?limit=5&fields=id,title,slug,published_at \
  -H "Authorization: Bearer wv_pub_EXAMPLE000000000000000000000000000"

```

A publishable key is safe in a browser. It sees only published articles, and it cannot write.

## What just happened

- **The Site came from your key.** Nothing you sent named a Site, and nothing you can send would change which one you reached.
- **Nothing became public by accident.** `POST /articles` created a draft. It took an explicit publish call to put it on the web, and that is true of every article, from this API or from the engine.
- **Publishing was free.** It made no external call, so it spent no credits and ignored your spend cap. Only `POST /pipeline/runs` bills.
- **The publishable key saw only what is published.** The same request with the secret key would also have returned drafts.

## Next

- [Authentication and keys](/docs/authentication) for scopes, rotation, and why demoting a colleague changes what their keys can do.
- [The content lifecycle](/docs/content-lifecycle) for scheduling, and for which statuses you may set.
- [Webhooks](/docs/webhooks) to be told when content changes instead of polling for it.
- [The API reference](/docs/api) for every operation.
