⚡ Quick Start

Create an application, store a secret, and read it back — in under five minutes.

Table of contents

0. Start the API

1
docker compose up -d

Wait for the health check to pass:

1
2
curl http://localhost:8080/health
# → 200 OK

Throughout this guide we use the default demo credentials. Change these before production use.

1
2
ADMIN_KEY="change-me-in-production"
BASE_URL="http://localhost:8080"

1. Create an application

A Grimoire application maps to one of your services (e.g. payments-api, frontend).

1
2
3
4
5
curl -s -X POST "$BASE_URL/api/management/applications" \
  -H "Authorization: Bearer $ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "my-service", "description": "My first Grimoire app"}' \
  | jq .

Response:

1
2
3
4
5
6
7
8
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "name": "my-service",
  "slug": "my-service",
  "description": "My first Grimoire app",
  "plainApiKey": "grm_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
  "createdAt": "2025-01-01T00:00:00Z"
}

Save the plainApiKey — it is shown once and cannot be retrieved again. If you lose it, use the rotate-key endpoint to generate a new one.

1
2
SLUG="my-service"
API_KEY="grm_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"

A local environment is automatically created alongside the application.


2. Store a secret

Create a secret (a named slot), then set its value for the local environment:

1
2
3
4
5
6
7
8
9
10
11
# Create the secret slot
curl -s -X POST "$BASE_URL/api/management/applications/$SLUG/secrets" \
  -H "Authorization: Bearer $ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "database-password"}' | jq .

# Set the value for the "local" environment
curl -s -X POST "$BASE_URL/api/management/applications/$SLUG/secrets/database-password/values" \
  -H "Authorization: Bearer $ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '[{"environmentSlug": "local", "value": "super-secret-db-pass", "isEnabled": true}]'

The value is immediately encrypted with AES-256-GCM before being stored.


3. Read the secret (Consumer API)

Use the application’s API key to read back the secret:

1
2
curl -s "$BASE_URL/api/consumer/secrets/database-password?environment=local" \
  -H "X-Api-Key: $API_KEY" | jq .

Response:

1
2
3
4
5
6
7
8
9
10
11
12
{
  "name": "database-password",
  "value": "super-secret-db-pass",
  "properties": {
    "enabled": true,
    "expiresOn": null,
    "notBefore": null,
    "version": 1,
    "createdOn": "2025-01-01T00:00:00Z",
    "updatedOn": null
  }
}

4. Store and read a configuration flag

1
2
3
4
5
6
7
8
9
# Create a config entry
curl -s -X POST "$BASE_URL/api/management/applications/$SLUG/configurations" \
  -H "Authorization: Bearer $ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"environmentSlug": "local", "key": "Feature:DarkMode", "value": "true"}' | jq .

# Read it back
curl -s "$BASE_URL/api/consumer/configurations/Feature:DarkMode?environment=local" \
  -H "X-Api-Key: $API_KEY" | jq .

Response:

1
2
3
4
5
{
  "key": "Feature:DarkMode",
  "value": "true",
  "label": "local"
}

5. Use the .NET client library

Add the Grimoire.Consumer project reference and wire it in Program.cs:

1
2
3
4
5
6
7
8
9
builder.Configuration.AddGrimoire(
    baseUrl:     "http://localhost:8080",
    apiKey:      "grm_a1b2c3d4e5f6...",
    environment: "local"
);

// The secret and config are now available as normal IConfiguration keys
var dbPassword    = builder.Configuration["database-password"];
var darkModeOn    = builder.Configuration["Feature:DarkMode"];

See the Client Library section for full details.


What’s next?