Skip to content

Configuration

Kirak keeps secrets and settings apart. Secrets (passwords, keys, tokens, connection strings that can hold a password) are read only from environment variables. Every other setting is read only from kirak.json, or from create_kirak_app() arguments. There is no silent environment fallback for a setting.


create_kirak_app() / Kirak() arguments <- code-level settings, highest priority
v
kirak.json manifest <- every non-secret setting
v
Runtime built-in defaults <- lowest priority
Environment variables (.env / shell) <- secrets only; never override a setting

kirak.local.json, when present, is merged over kirak.json first (see Per-environment values), so it sits at the kirak.json level of this list. .env files are loaded automatically by Kirak via python-dotenv at startup. If you upgrade a project that still sets a retired variable such as DB_HOST or KIRAK_BASE_URL, startup logs a warning that names the kirak.json key that replaces it.


These parameters are passed directly to the factory and take precedence over kirak.json.

Parameter Type Default Description
models_path str – Required. Path to a models.json file or a directory of *.json files.
title str "Kirak API" FastAPI application title.
description str "API built with Kirak Runtime" FastAPI application description.
version str "1.0.0" API version string.
enable_cors bool False Enable CORS middleware.
cors_origins list[str] [] Allowed CORS origins.
modules list[str] [] Modules to enable: notifications, payments, ai, storage, scheduler, monitoring, vector. If not passed, falls back to kirak.json modules.
kirak_prefix str "" URL prefix for all CRUD routes.
auth_prefix str None (/auth) URL path of the auth routes; replaces /auth ("/api/auth" -> /api/auth/login). Links Kirak builds (emails, social redirect_uri) follow it. The Kirak client SDK calls the default /auth routes.
module_prefixes dict {} Per-module URL prefix overrides, e.g. {"notifications": "/notif"}.
middlewares list[tuple] [] Extra ASGI middleware as (MiddlewareClass, options_dict) pairs.
on_startup callable None async (app) callback – runs before Kirak initialises.
on_kirak_ready callable None async (kirak) callback – runs after connect(), before mount_routers(). Register hooks here.
on_shutdown callable None async (app) callback – runs after Kirak disconnects.

Every Kirak project has a kirak.json, placed next to your models_path or in the project root (kirak new creates it). Kirak searches for it at startup and refuses to start without one. Invalid JSON or a schema violation prevents startup with a message naming the file and the key. Values that differ per environment go in an optional kirak.local.json next to it.

{
"version": "1",
"title": "My API",
"description": "Powered by Kirak",
"project_name": "My App",
"base_url": "https://api.example.com",
"modules": ["notifications", "payments", "scheduler"],
"database": {
"type": "mysql",
"host": "localhost",
"name": "myapp"
},
"cors": {
"enabled": true,
"origins": ["https://app.example.com", "https://admin.example.com"]
},
"rate_limit": {
"enabled": true,
"default_max_requests": 100,
"default_window_seconds": 60,
"trusted_proxy_ips": []
},
"custom": {
"feature_flag_new_checkout": true
}
}

Only secrets live in .env. Every other setting, including the database host and the allowed CORS origins, is in kirak.json.

kirak.json is committed and is the same in every environment. Some values are not: the database host on your laptop is localhost, in Docker it is db; base_url and the CORS origins change between staging and production. Put those in an optional kirak.local.json in the same directory as kirak.json.

{
"base_url": "https://api.example.com",
"database": { "host": "db.internal" },
"cors": { "origins": ["https://app.example.com"] }
}

How it is applied. When Kirak loads kirak.json it looks for kirak.local.json beside it and merges the two before validating the result:

  • Objects merge key by key, at any depth. Keys you leave out keep the value from kirak.json.
  • Everything else is replaced as a whole: strings, numbers, booleans and lists. A cors.origins list in kirak.local.json replaces the list in kirak.json, it is not appended to it.

With this kirak.json:

{
"base_url": "http://localhost:8000",
"database": { "host": "localhost", "name": "myapp", "user": "root" },
"cors": { "origins": ["http://localhost:3000"], "allow_credentials": true }
}

and the kirak.local.json above, Kirak runs with:

{
"base_url": "https://api.example.com",
"database": { "host": "db.internal", "name": "myapp", "user": "root" },
"cors": { "origins": ["https://app.example.com"], "allow_credentials": true }
}

Rules

  • It accepts exactly the keys kirak.json accepts, and the merged result is validated like any manifest. A key that is not allowed (a typo, or a secret such as database.password) fails startup. Secrets stay in environment variables; see Configuration Precedence.
  • It is found only next to a kirak.json. A kirak.local.json on its own is ignored, and kirak.json is still required.
  • Do not commit it. The .gitignore that kirak new creates lists it. Commit the values every environment shares in kirak.json.
  • It is read once at startup. Restart the app after changing it.
  • kirak.manifest at runtime holds the merged values, so kirak.manifest.base_url is the environment’s value.

Providing it per environment

Environment How
Local development Create the file by hand next to kirak.json
Docker Mount it read-only: - ./deploy/kirak.local.docker.json:/app/kirak.local.json:ro
Docker Compose 2.23.1+ Define it inline with a top-level configs entry (content: |) and mount that at /app/kirak.local.json
Kubernetes Mount a ConfigMap key as the file kirak.local.json in the app directory
CI Write it in a build step before starting the app

Errors

Message Cause
Invalid JSON in kirak.local.json (<path>) The override file is not valid JSON, or is not a JSON object
kirak.json validation failed (<path>) The merged result breaks the schema; the message names the offending key
Key Type Default Description
version string "1" Manifest schema version.
title string "" API title (informational).
description string "" API description (informational).
modules array [] Modules to enable. Valid values: notifications, payments, ai, storage, scheduler, monitoring, vector. Used only when modules= is not passed to create_kirak_app().
cors.enabled bool true Enable CORS middleware.
cors.origins array of strings [] Allowed origins, for example ["https://app.example.com"]. The old cors.origins_env key was removed; a kirak.json that still has it fails to load with a message pointing here.
project_name string "" Display name used in OTP SMS messages, as the authenticator-app issuer in MFA QR codes, and as the default app_name of SMS templates.
base_url string "" Public base URL of the app (for example https://api.example.com), without a trailing slash. Used to build links in verification and password reset emails and the social login callback URLs. Required for registration to succeed.
docs.enabled bool true Serve GET /docs, the app’s HTTP API in Markdown for AI agents; see API Docs Endpoint. false registers no route (404). Does not affect openapi.json.
docs.path string "/docs" Path of that document.
docs.public bool true Serve it without a credential. false requires a signed-in caller or an API key (401 otherwise). Does not affect openapi.json, which describes the same models and access rules: set openapi.public too.
openapi.enabled bool true Serve GET /openapi.json, with one set of CRUD paths per model. false registers no route (404). Does not affect /docs.
openapi.public bool true Serve it without a credential. false requires a signed-in caller or an API key (401 otherwise). Independent of docs.public.
bulk_chunk_size int 500 Records per chunk for bulk create, update, delete and destroy. Reduce it if you hit database packet-size limits.
database.* object see Database Database connection settings.
branding.* object see Email Template Branding Logo, contact details and colours of the built-in emails.
cors.allow_credentials bool true Allow cookies and credentials in CORS requests.
cors.allow_methods array ["*"] Allowed HTTP methods.
cors.allow_headers array ["*"] Allowed request headers.
rate_limit.enabled bool true Global kill switch – disables per-model CRUD rate limiting and the hardcoded auth endpoint limits when false.
rate_limit.default_max_requests int 100 Applied to any model with no rate_limit block of its own.
rate_limit.default_window_seconds int 60 Window for the default limit.
rate_limit.trusted_proxy_ips array of strings [] IPs allowed to set X-Forwarded-For/X-Real-IP for rate-limit IP resolution – see Rate Limiting.
log_level string "INFO" Level of the kirak logger: DEBUG, INFO, WARNING, ERROR or CRITICAL.
log_max_size_mb int 5 Size at which the shared log file kirak.log rotates, in megabytes.
log_backup_count int 1 Number of rotated log files kept.
assets_path string null (assets/) Project directory searched first for overrides of bundled assets such as email templates; see asset resolution.
strict_access bool false When true, startup fails with ConfigurationError if any model has a missing or invalid access block. Without it, such a model starts with a warning and denies every request.
hook_timeout_seconds number 5.0 Maximum seconds an async def hook may run before it is cancelled and skipped (minimum 0.1). Applies to the hooks of every module. Only kirak.json sets it: the KIRAK_HOOK_TIMEOUT environment variable is no longer read.
log_path string "logs" Directory of the shared log file kirak.log, relative to the working directory or absolute. Only kirak.json sets it: the LOG_PATH environment variable is no longer read.
custom object {} Arbitrary key/value pairs – accessible at runtime via kirak.manifest.custom.

Access manifest values at runtime:

def on_kirak_ready(kirak):
if kirak.manifest.custom.get("feature_flag_new_checkout"):
# wire up new checkout hooks
pass
# Check which modules were loaded
print(kirak.manifest.modules) # ['notifications', 'payments']

The database block of kirak.json holds every database setting except the password. The password is a secret and is read from the DB_PASSWORD environment variable.

"database": {
"type": "postgres",
"host": "db.internal",
"name": "myapp",
"user": "app"
}
Key Default Required Description
database.type mysql Database engine: mysql or postgres (postgresql is accepted).
database.host localhost Database hostname or IP.
database.port 3306 / 5432 Port. The default follows database.type: 3306 (MySQL), 5432 (PostgreSQL).
database.user root Database user.
database.name – Yes Database name. Startup raises ConfigurationError if empty.
database.pool_min 1 Minimum pool connections (1-100). Must not exceed pool_max.
database.pool_max 10 Maximum pool connections (1-100).
database.pool_recycle_seconds 3600 Seconds before idle connections are recycled. MySQL only.
Environment variable Required Description
DB_PASSWORD Database password. Empty by default.

The old DB_TYPE, DB_HOST, DB_PORT, DB_USER, DB_NAME, DB_POOL_MIN, DB_POOL_MAX and DB_POOL_RECYCLE variables are no longer read. If one is still set, startup logs a warning that names the kirak.json key that replaces it.

Switching from MySQL to PostgreSQL:

Terminal window
pip install "kirak[postgres]"
"database": { "type": "postgres", "name": "myapp" }

No application code changes needed – the dialect layer handles all SQL differences transparently.


All auth variables use the KIRAK_AUTH_ prefix.

Variable Default Required Description
KIRAK_AUTH_JWT_SECRET_KEY – Yes Access token signing key. Must be >= 32 bytes. Startup fails if unset or too short.
KIRAK_AUTH_JWT_REFRESH_SECRET_KEY – Refresh token signing key. Falls back to KIRAK_AUTH_JWT_SECRET_KEY if not set. Recommended to set separately in production.
KIRAK_AUTH_JWT_OLD_SECRET_KEY – Previous access token signing key. Set during key rotation to keep tokens signed with the old key valid until they expire. Once all old tokens have expired, remove this variable.
KIRAK_AUTH_JWT_REFRESH_OLD_SECRET_KEY – Previous refresh token signing key. Mirrors KIRAK_AUTH_JWT_OLD_SECRET_KEY for refresh tokens. Falls back to KIRAK_AUTH_JWT_OLD_SECRET_KEY if not set.
KIRAK_AUTH_API_KEY_SECRET KIRAK_AUTH_JWT_SECRET_KEY Keys the stored hash of API keys. Set it in production: without it API keys are hashed with the JWT secret, and rotating that secret invalidates every API key (Kirak logs a warning at startup while it is unset). Keys created before you set it keep working until the JWT secret changes; recreate them to move them onto this secret.

Token lifetimes and the signing algorithm are kirak.json manifest settings under "auth", not environment variables:

Setting Default Accepted values
jwt_algorithm HS256 HS256, HS384, HS512 (asymmetric algorithms are rejected to prevent algorithm-confusion attacks)
access_token_expire_hours 1 any integer >= 1
access_token_expire_minutes unset any integer >= 1. When set, it wins over access_token_expire_hours; use it for lifetimes under an hour (for example 5)
refresh_token_expire_days 14 any integer >= 1

Generate a secure key:

Terminal window
python -c "import secrets; print(secrets.token_hex(32))"
Variable Default Required Description
KIRAK_AUTH_VERIFICATION_KEY – Yes Fernet key for signing email verification and password reset links.
KIRAK_AUTH_ENCRYPTION_KEY derived from KIRAK_AUTH_JWT_SECRET_KEY AES-256-GCM key encrypting social-login token data (auth_social.extra_data) and MFA TOTP secrets (auth_mfa.totp_secret). Falls back to a SHA-256 derivation of the JWT secret with a startup warning if unset – set explicitly in production. Unrelated to KIRAK_AUTH_VERIFICATION_KEY (Fernet, used only for verification/reset links).

Generate a Fernet key:

from cryptography.fernet import Fernet
print(Fernet.generate_key().decode())

The links themselves are configured in kirak.json:

Key Default Description
base_url – Required. Base URL of your application (e.g. https://api.example.com). Required to build verification and reset links, and for registration to succeed at all, even without email sending configured.
auth.forgot_password_page_url {base_url}/auth/forgot-password (/auth is auth_prefix when set) Frontend URL for the password reset form. Included in password reset emails.

email_verification_required (default true) is also a kirak.json manifest setting under "auth", not an environment variable – set "email_verification_required": false in development to skip the verification step.

kirak.json key Default Description
project_name – Display name used in OTP SMS messages and as the TOTP issuer name in MFA QR codes (e.g. "My App").

The branding block of kirak.json controls the appearance of Kirak’s built-in email templates (verification, password reset, welcome, invoice, etc.). Values you pass in a template’s own parameters win over these defaults.

Key Default Description
branding.logo "" URL of your logo image, inserted into email headers.
branding.support_email "" Support email address shown in email footers.
branding.website_url "" Your website URL, used for footer links.
branding.login_url "" Login page URL, linked in verification and reset emails.
branding.primary_bg_color "#000000" Primary background color (hex).
branding.secondary_bg_color "#E7054C" Accent/button background color (hex).
branding.primary_text_color "#000000" Primary text color (hex).
branding.secondary_text_color "#FFFFFF" Text color on accent backgrounds (hex).

The LOGO, SUPPORT_EMAIL, WEBSITE_URL, LOGIN_URL and colour environment variables are no longer read.

Override any template entirely by placing a same-named .py file under assets/notifications/templates/email/ in your project (see asset resolution).

These are kirak.json manifest settings under "auth", not environment variables:

Key Default Description
bcrypt_rounds 13 bcrypt work factor. Higher = more secure, slower. Do not set below 12 in production.
password_complexity true Minimum length is always 12 characters regardless of this flag. When true (default), also requires at least one uppercase letter, one lowercase letter, one digit, and one special character from `!@#$%^&*(),.?“:{}

Set both settings to enable an HttpOnly; Secure; SameSite=Lax access-token cookie alongside the JWT response body. The cookie is read as a third credential (after Bearer, after API key), so browsers that send only the cookie are authenticated without an Authorization header. These are kirak.json manifest settings under "auth", not environment variables:

{ "auth": { "cookie_name": "kirak_token", "cookie_domain": ".example.com" } }
Key Default Description
cookie_name – Cookie name. When set, access tokens are written to an HttpOnly cookie on login, verify-OTP, refresh-token, and social callback responses, and read back on every authenticated request.
cookie_domain – Cookie domain. Use .yourdomain.com (note the leading dot) to share across subdomains.

Configure only the providers you use. Client IDs, key and team IDs and redirect URIs are settings in the auth.social block of kirak.json. Client secrets and the Apple private key are secrets and stay in the environment.

"auth": {
"social_providers": ["google", "apple"],
"social": {
"google": { "client_id": "123456-abc.apps.googleusercontent.com" },
"apple": { "client_id": "com.example.app.service", "team_id": "ABCDE12345", "key_id": "K1L2M3N4" }
},
"apple_web_callback_url": "https://app.example.com/auth/callback"
}

The redirect URI of every provider defaults to {base_url}/auth/{provider}/callback (/auth is auth_prefix when one is set). Set redirect_uri in a provider’s block only to override it.

Provider auth.social.<provider> keys Environment secrets
google client_id, redirect_uri, audience (client ids a mobile sign-in ID token may be issued to; default [client_id]) KIRAK_AUTH_GOOGLE_CLIENT_SECRET
github client_id, redirect_uri KIRAK_AUTH_GITHUB_CLIENT_SECRET
apple client_id, team_id, key_id, redirect_uri, audience (as for google; add the iOS bundle id for mobile sign-in) KIRAK_AUTH_APPLE_PRIVATE_KEY
facebook client_id, redirect_uri KIRAK_AUTH_FACEBOOK_CLIENT_SECRET
instagram client_id, redirect_uri KIRAK_AUTH_INSTAGRAM_CLIENT_SECRET
tiktok client_key, redirect_uri KIRAK_AUTH_TIKTOK_CLIENT_SECRET

The catalog names google-oauth2 and apple-id in social_providers use the google and apple blocks.

Other settings:

Setting Where Description
auth.apple_web_callback_url kirak.json Frontend URL for the post-Apple-callback redirect (web flows).
KIRAK_AUTH_WEB_TOKEN_SECRET environment Signing secret for short-lived Apple web-auth state tokens. Falls back to KIRAK_AUTH_JWT_SECRET_KEY if not set. Set a separate value in production to scope exposure.

Providers that are not in the table (Discord, LinkedIn, …) take their client ID and secret through the social-core settings; see Social Auth.

The OAuth strategy takes its host and scheme from base_url, so KIRAK_AUTH_HOST and KIRAK_AUTH_HTTPS are no longer needed or read. Use an http:// base_url for local development without TLS.

The old KIRAK_AUTH_<PROVIDER>_CLIENT_ID, _CLIENT_KEY, _TEAM_ID, _KEY_ID, _REDIRECT_URI and KIRAK_AUTH_APPLE_WEB_AUTH_CALLBACK_URL variables, and the direct SOCIAL_AUTH_* variables, are no longer read.

auth key Type Description
jwt_algorithm string Token signing algorithm. Asymmetric algorithms are rejected. Default HS256.
access_token_expire_hours integer Access token lifetime in hours. Default 1.
access_token_expire_minutes integer Access token lifetime in minutes, for lifetimes under an hour. When set, wins over access_token_expire_hours.
refresh_token_expire_days integer Refresh token lifetime in days. Default 14.
email_verification_required boolean Require users to verify their email before signing in. Default true.
cookie_name string When set, access tokens are also written to an HttpOnly cookie of this name on login, OTP verification, refresh and social callbacks.
cookie_domain string Cookie domain. A leading dot (.example.com) shares it across subdomains.
social_providers array Social login providers to enable, by social-core name (e.g. google-oauth2, github, apple-id).
social object Non-secret settings per social provider (client IDs, redirect URIs, and any other setting the provider’s social-core backend reads, as a lowercase key, e.g. auth0: {“domain”: …}). Client secrets and the Apple private key are environment variables: KIRAK_AUTH_CLIENT_SECRET, or SOCIAL_AUTHSECRET for other providers; other secret settings (client_assertion, sp_private_key, bot_token, api_key) are SOCIAL_AUTH_. google-oauth2 and apple-id use the google and apple blocks.
forgot_password_page_url string Frontend page with the password reset form, linked from reset emails. Default {base_url}/auth/forgot-password (/auth is auth_prefix when set).
apple_web_callback_url string Frontend URL the Apple web sign-in flow redirects to after its callback.
bcrypt_rounds integer bcrypt work factor for password hashes. Do not go below 12 in production. Default 13.
password_complexity boolean Require an uppercase letter, a lowercase letter, a digit and a special character. The minimum length of 12 always applies. Default true.

Requires pip install "kirak[notifications-ses]" for email (AWS SES), pip install "kirak[notifications-sns]" for SMS (AWS SNS), pip install "kirak[notifications-sendgrid]" for email (SendGrid), pip install "kirak[notifications-firebase]" for push (FCM), pip install "kirak[notifications-twilio]" for SMS (Twilio) and pip install "kirak[notifications-apn]" for push (Apple). SMTP, Mailgun, Postmark, SparkPost, Brevo, Resend, Vonage, Plivo, MessageBird, Africa’s Talking, Termii, FastSMS, Huawei, Expo, Slack, Discord, Telegram and webhooks need no extra install.

Each channel (email, sms, push, im, webhook) declares its provider instances and default in kirak.json under "notifications". Only credentials are environment variables (prefix KIRAK_NOTIFICATION_).

{
"notifications": {
"email_from_address": "no-reply@example.com",
"email_from_name": "My App",
"sms_from_number": null,
"attachment_base_path": null,
"email": {
"default_provider": "ses",
"providers": { "ses": { "type": "aws_ses", "aws_region": "us-east-1" } }
},
"sms": {
"default_provider": "sns",
"providers": { "sns": { "type": "aws_sns", "aws_region": "us-east-1" } }
},
"push": {
"default_provider": "fcm",
"providers": { "fcm": { "type": "firebase", "firebase_project_id": "my-project" } }
},
"im": {
"default_provider": "ops_slack",
"providers": { "ops_slack": { "type": "slack" } }
},
"webhook": {
"default_provider": "billing",
"providers": { "billing": { "type": "generic", "url": "https://billing.example.com/hooks" } }
}
}
}
notifications key Type Description
email_from_address string or null Sender address, e.g. no-reply@example.com.
email_from_name string or null Sender display name.
sms_from_number string or null SMS sender number or name, used when a provider instance sets none.
attachment_base_path string or null Directory email attachment paths are resolved from.
email object Email providers (e.g. aws_ses, sendgrid, smtp).
sms object SMS providers (e.g. aws_sns, twilio).
push object Push providers (e.g. firebase, apn, huawei).
im object Instant messaging providers (e.g. slack, discord, telegram).
webhook object Outgoing webhook providers (e.g. generic).
Each channel key (email, sms, push, im, webhook) is a provider set: default_provider (instance name, required when providers is non-empty) and providers (map of instance name to settings). Names are lowercase letters, digits and _, starting with a letter. Every entry needs type. A channel left out is unavailable.

Email templates are not configured via a base-path setting – they resolve through asset resolution at a fixed location (assets/notifications/templates/email/ in your project, falling back to Kirak’s bundled templates).

Settings go in the provider entry in kirak.json; secrets are environment variables, one set per provider instance: KIRAK_NOTIFICATION_<CHANNEL>_<INSTANCE>_<FIELD>, upper-cased. Credentials in kirak.json are rejected. AWS credentials (SES, SNS) are optional; boto3 uses its default credential chain when they are unset (set both keys or neither).

<INSTANCE> is the provider instance’s name in kirak.json, upper-cased: an instance named main reads ..._MAIN_....

email / aws_ses (pip install "kirak[notifications-ses]") – Email through Amazon SES.

Credential check (check()): GetSendQuota (also: is the account in the sandbox).

Name Where Required / default Description
aws_region kirak.json AWS region, e.g. us-east-1.
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_ACCESS_KEY environment AWS access key ID. Optional: boto3’s default credential chain is used when unset.
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_SECRET_KEY environment AWS secret access key. Set together with the access key.

email / sendgrid (pip install "kirak[notifications-sendgrid]") – Email through SendGrid.

Credential check (check()): GET /v3/scopes; mail.send must be granted.

Name Where Required / default Description
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_API_KEY environment required SendGrid API key (starts with SG.).

email / smtp (no extra install) – Email through any SMTP server.

Credential check (check()): Connect, STARTTLS as configured, LOGIN, QUIT; nothing is sent.

Name Where Required / default Description
smtp_host kirak.json required SMTP server host.
smtp_port kirak.json default 587 SMTP server port.
smtp_use_tls kirak.json default True Use STARTTLS.
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_USERNAME environment SMTP username. Leave unset for a server without authentication.
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_PASSWORD environment SMTP password.

email / mailgun (no extra install) – Email through Mailgun.

Credential check (check()): GET /v3/domains/ (also: is the domain verified).

Name Where Required / default Description
domain kirak.json required Sending domain, e.g. mg.example.com.
region kirak.json default us Account region: us or eu.
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_API_KEY environment required Mailgun API key.

email / postmark (no extra install) – Email through Postmark.

Credential check (check()): GET /server.

Name Where Required / default Description
message_stream kirak.json default outbound Message stream to send through.
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_SERVER_TOKEN environment required Postmark server API token.

email / sparkpost (no extra install) – Email through SparkPost.

Credential check (check()): GET /api/v1/account; a send-only key cannot read it, so that result is unverified.

Name Where Required / default Description
region kirak.json default us Account region: us or eu.
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_API_KEY environment required SparkPost API key with the Transmissions: Read/Write permission.

email / brevo (no extra install) – Email through Brevo (formerly Sendinblue).

Credential check (check()): GET /v3/account.

Name Where Required / default Description
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_API_KEY environment required Brevo API key (xkeysib-…).

email / resend (no extra install) – Email through Resend.

Credential check (check()): GET /domains; a sending-only key is reported as valid.

Name Where Required / default Description
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_API_KEY environment required Resend API key (re_…).

sms / aws_sns (pip install "kirak[notifications-sns]") – SMS through Amazon SNS.

Credential check (check()): GetSMSSandboxAccountStatus.

Name Where Required / default Description
aws_region kirak.json AWS region, e.g. us-east-1.
KIRAK_NOTIFICATION_SMS_<INSTANCE>_ACCESS_KEY environment AWS access key ID. Optional: boto3’s default credential chain is used when unset.
KIRAK_NOTIFICATION_SMS_<INSTANCE>_SECRET_KEY environment AWS secret access key. Set together with the access key.

sms / twilio (pip install "kirak[notifications-twilio]") – SMS through Twilio.

Credential check (check()): GET /2010-04-01/Accounts/.json (status, trial).

Name Where Required / default Description
from_number kirak.json Sender number. Default: notifications.sms_from_number.
messaging_service_sid kirak.json Twilio Messaging Service to send from; wins over from_number.
KIRAK_NOTIFICATION_SMS_<INSTANCE>_ACCOUNT_SID environment required Twilio account SID.
KIRAK_NOTIFICATION_SMS_<INSTANCE>_AUTH_TOKEN environment required Twilio auth token.

sms / vonage (no extra install) – SMS through Vonage (formerly Nexmo).

Credential check (check()): GET /account/get-balance.

Name Where Required / default Description
from_number kirak.json Sender: a phone number, or an alphanumeric sender ID where the provider and country allow one. Default: notifications.sms_from_number.
KIRAK_NOTIFICATION_SMS_<INSTANCE>_API_KEY environment required Vonage API key.
KIRAK_NOTIFICATION_SMS_<INSTANCE>_API_SECRET environment required Vonage API secret.

sms / plivo (no extra install) – SMS through Plivo.

Credential check (check()): GET /v1/Account/<auth_id>/.

Name Where Required / default Description
from_number kirak.json Sender: a phone number, or an alphanumeric sender ID where the provider and country allow one. Default: notifications.sms_from_number.
KIRAK_NOTIFICATION_SMS_<INSTANCE>_AUTH_ID environment required Plivo Auth ID.
KIRAK_NOTIFICATION_SMS_<INSTANCE>_AUTH_TOKEN environment required Plivo Auth Token.

sms / messagebird (no extra install) – SMS through MessageBird (Bird).

Credential check (check()): GET /balance.

Name Where Required / default Description
from_number kirak.json Sender: a phone number, or an alphanumeric sender ID where the provider and country allow one. Default: notifications.sms_from_number.
KIRAK_NOTIFICATION_SMS_<INSTANCE>_ACCESS_KEY environment required MessageBird access key.

sms / africastalking (no extra install) – SMS through Africa’s Talking.

Credential check (check()): GET /version1/user (the account balance); username sandbox is test mode.

Name Where Required / default Description
username kirak.json required Africa’s Talking app username; sandbox uses the sandbox API.
from_number kirak.json Registered short code or alphanumeric sender ID. Default: notifications.sms_from_number, else Africa’s Talking’s shared sender.
KIRAK_NOTIFICATION_SMS_<INSTANCE>_API_KEY environment required Africa’s Talking API key.

sms / termii (no extra install) – SMS through Termii.

Credential check (check()): GET /api/get-balance.

Name Where Required / default Description
base_url kirak.json default https://api.ng.termii.com Your account’s API base URL, shown on the Termii dashboard.
channel kirak.json default generic Route: generic (promotional) or dnd (transactional, e.g. OTPs; needs activation by Termii).
from_number kirak.json Sender: a phone number, or an alphanumeric sender ID where the provider and country allow one. Default: notifications.sms_from_number.
KIRAK_NOTIFICATION_SMS_<INSTANCE>_API_KEY environment required Termii API key.

sms / fastsms (no extra install) – SMS through FastSMS (UK).

Credential check (check()): Action=CheckCredits.

Name Where Required / default Description
from_number kirak.json Sender: a phone number, or an alphanumeric sender ID where the provider and country allow one. Default: notifications.sms_from_number.
KIRAK_NOTIFICATION_SMS_<INSTANCE>_TOKEN environment required FastSMS API token (NetMessenger account settings).

push / firebase (pip install "kirak[notifications-firebase]") – Push notifications through Firebase Cloud Messaging.

Credential check (check()): A dry-run send to an invalid device token; nothing is delivered.

Name Where Required / default Description
firebase_credentials_path kirak.json Path of the Firebase service account JSON file.
firebase_project_id kirak.json Firebase project ID.

push / apn (pip install "kirak[notifications-apn]") – Push notifications to Apple devices through APNs.

Credential check (check()): A push to an invalid device token; nothing is delivered.

Name Where Required / default Description
apn_key_path kirak.json required Path of the .p8 signing key file.
apn_key_id kirak.json required Key ID of the signing key.
apn_team_id kirak.json required Apple developer team ID.
apn_bundle_id kirak.json required App bundle ID (the APNs topic).
apn_use_sandbox kirak.json default False Send through the APNs sandbox (development builds).

push / huawei (no extra install) – Push notifications to Huawei devices through Push Kit.

Credential check (check()): POST the OAuth token URL (client credentials).

Name Where Required / default Description
app_id kirak.json required Huawei app ID.
KIRAK_NOTIFICATION_PUSH_<INSTANCE>_CLIENT_SECRET environment required Huawei app client secret.

push / expo (no extra install) – Push notifications to Expo apps through the Expo push service.

Credential check (check()): None: Expo has no endpoint that checks an access token without sending.

Name Where Required / default Description
KIRAK_NOTIFICATION_PUSH_<INSTANCE>_ACCESS_TOKEN environment Expo access token, needed only when push security is enabled for the project.

im / slack (no extra install) – Messages to Slack channels.

Credential check (check()): POST auth.test; the token must have chat:write.

Name Where Required / default Description
KIRAK_NOTIFICATION_IM_<INSTANCE>_BOT_TOKEN environment required Bot token.

im / discord (no extra install) – Messages to Discord channels.

Credential check (check()): GET /users/@me.

Name Where Required / default Description
KIRAK_NOTIFICATION_IM_<INSTANCE>_BOT_TOKEN environment required Bot token.

im / telegram (no extra install) – Messages to Telegram chats.

Credential check (check()): getMe.

Name Where Required / default Description
KIRAK_NOTIFICATION_IM_<INSTANCE>_BOT_TOKEN environment required Bot token.

webhook / generic (no extra install) – Signed HTTP POST to your own systems.

Credential check (check()): None: a receiver can only be tested by sending to it; the url is checked.

Name Where Required / default Description
url kirak.json Destination URL.
allow_url_override kirak.json default False Let a call pass its own destination URL.
timeout kirak.json default 10.0 Request timeout in seconds.
KIRAK_NOTIFICATION_WEBHOOK_<INSTANCE>_SECRET_KEY environment HMAC signing key; requests are unsigned when unset.

Requires pip install "kirak[payments-stripe]", pip install "kirak[payments-razorpay]", or pip install "kirak[payments-square]" depending on your gateway; PayPal, Paddle, Paystack, Flutterwave, Mercado Pago, Xendit, Airwallex, Omise and Telr need no extra.

Providers are declared in kirak.json under "payments" as named instances. Each instance has a type (stripe, razorpay, square, paypal, paddle, paystack, flutterwave, mercadopago, xendit, airwallex, omise, telr, stripe_connect, or a custom type) and a default_provider names the one used when a call passes no provider:

"payments": {
"default_provider": "stripe",
"providers": {
"stripe": { "type": "stripe" },
"square": { "type": "square", "location_id": "L123", "environment": "sandbox" }
},
"success_url": "/payment/success",
"cancel_url": "/payment/cancel"
}
payments key Type Description
default_provider string Instance name used when a call names no provider. Must be one of the instances under providers.
providers object Payment provider instances (types stripe, stripe_connect, razorpay, square, or a custom type), by instance name.
success_url string or null Redirect after a successful payment. Each provider instance can override it.
cancel_url string or null Redirect after a cancelled payment. Each provider instance can override it.
require_auth boolean Require a signed-in caller on the payment routes. false allows guest checkout. Default true.
The currency is passed with each call ("currency": "USD"), not set in kirak.json; see Payments.

Secrets are read from the environment, one set per instance: KIRAK_PAYMENT_<INSTANCE>_<FIELD>, upper-cased. Secrets in kirak.json are rejected. Each provider’s setup (key prefixes, webhook URL and signature header) is described on its own page under Payments, including which Stripe Connect webhook endpoint each secret verifies.

<INSTANCE> is the provider instance’s name in kirak.json, upper-cased: an instance named main reads ..._MAIN_....

stripe (pip install "kirak[payments-stripe]") – Stripe Checkout, subscriptions, saved payment methods, off-session charges and disputes.

Credential check (check()): GET /v1/balance.

Name Where Required / default Description
success_url kirak.json default /payment/success Redirect after a successful payment. Overrides payments.success_url.
cancel_url kirak.json default /payment/cancel Redirect after a cancelled payment. Overrides payments.cancel_url.
KIRAK_PAYMENT_<INSTANCE>_SECRET_KEY environment required Stripe secret API key (sk_live_… or sk_test_…).
KIRAK_PAYMENT_<INSTANCE>_WEBHOOK_SECRET environment Webhook signing secret (whsec_…); without it every webhook is refused.

stripe_connect (pip install "kirak[payments-stripe]") – Stripe Connect marketplace: merchant onboarding, checkout on behalf of merchants, platform fees.

Credential check (check()): GET /v1/account (the platform account).

Name Where Required / default Description
success_url kirak.json default /payment/success Redirect after a successful payment. Overrides payments.success_url.
cancel_url kirak.json default /payment/cancel Redirect after a cancelled payment. Overrides payments.cancel_url.
refresh_url kirak.json default /connect/onboard/refresh Onboarding URL Stripe sends a merchant back to when a link expired.
return_url kirak.json default /connect/onboard/return URL Stripe sends a merchant to after onboarding.
KIRAK_PAYMENT_<INSTANCE>_SECRET_KEY environment required Stripe secret API key of the platform account.
KIRAK_PAYMENT_<INSTANCE>_WEBHOOK_SECRET environment Signing secret of the connected-accounts webhook endpoint.
KIRAK_PAYMENT_<INSTANCE>_PLATFORM_WEBHOOK_SECRET environment Signing secret of the platform-account webhook endpoint (checkout, refunds, saved methods).

razorpay (pip install "kirak[payments-razorpay]") – Razorpay payments, subscriptions, saved payment methods (mandates) and disputes.

Credential check (check()): GET /v1/payments?count=1.

Name Where Required / default Description
success_url kirak.json default /payment/success Redirect after a successful payment. Overrides payments.success_url.
cancel_url kirak.json default /payment/cancel Redirect after a cancelled payment. Overrides payments.cancel_url.
KIRAK_PAYMENT_<INSTANCE>_KEY_ID environment required Razorpay key ID (rzp_live_… or rzp_test_…).
KIRAK_PAYMENT_<INSTANCE>_KEY_SECRET environment required Razorpay key secret.
KIRAK_PAYMENT_<INSTANCE>_WEBHOOK_SECRET environment Webhook secret; needed to verify webhooks.

square (pip install "kirak[payments-square]") – Square payments, subscriptions, saved cards and disputes.

Credential check (check()): GET /v2/locations/<location_id>.

Name Where Required / default Description
location_id kirak.json required Square location that takes the payments.
environment kirak.json default sandbox “sandbox” or “production”.
webhook_notification_url kirak.json The exact public URL Square posts webhooks to; part of the signature check.
success_url kirak.json default /payment/success Redirect after a successful payment. Overrides payments.success_url.
cancel_url kirak.json default /payment/cancel Redirect after a cancelled payment. Overrides payments.cancel_url.
KIRAK_PAYMENT_<INSTANCE>_ACCESS_TOKEN environment required Square access token (production or sandbox).
KIRAK_PAYMENT_<INSTANCE>_WEBHOOK_SIGNATURE_KEY environment Webhook signature key; needed to verify webhooks.

paypal (no extra install) – PayPal Checkout: one-time payments, subscriptions, vaulted PayPal accounts, off-session charges and disputes (read-only).

Credential check (check()): POST /v1/oauth2/token; then GET the webhook named by webhook_id.

Name Where Required / default Description
environment kirak.json default sandbox “sandbox” or “live”.
success_url kirak.json default /payment/success Redirect after a successful payment. Overrides payments.success_url.
cancel_url kirak.json default /payment/cancel Redirect after a cancelled payment. Overrides payments.cancel_url.
KIRAK_PAYMENT_<INSTANCE>_CLIENT_ID environment required PayPal REST app client ID.
KIRAK_PAYMENT_<INSTANCE>_CLIENT_SECRET environment required PayPal REST app secret.
KIRAK_PAYMENT_<INSTANCE>_WEBHOOK_ID environment ID of the webhook registered in the app; needed to verify webhooks.

paddle (no extra install) – Paddle Billing (merchant of record): one-time payments, subscriptions and one-time charges on a subscription.

Credential check (check()): GET /event-types.

Name Where Required / default Description
environment kirak.json default sandbox “sandbox” or “production”.
default_tax_category kirak.json default standard Tax category of the product created for a payment without price_id.
checkout_url kirak.json Approved page that loads Paddle.js; the account’s default payment link otherwise.
KIRAK_PAYMENT_<INSTANCE>_API_KEY environment required Paddle API key.
KIRAK_PAYMENT_<INSTANCE>_WEBHOOK_SECRET environment Secret of the notification destination; needed to verify webhooks.

paystack (no extra install) – Paystack: one-time payments, subscriptions, saved cards, off-session charges and disputes (read-only).

Credential check (check()): GET /balance.

Name Where Required / default Description
environment kirak.json default test “test” or “live”; must match the secret key.
success_url kirak.json default /payment/success Redirect after a successful payment. Overrides payments.success_url.
KIRAK_PAYMENT_<INSTANCE>_SECRET_KEY environment required Paystack secret key (sk_test_… or sk_live_…); also verifies webhooks.

flutterwave (no extra install) – Flutterwave (API v3): one-time payments, subscriptions, saved cards, off-session charges and disputes (read-only).

Credential check (check()): GET /v3/balances.

Name Where Required / default Description
environment kirak.json default test “test” or “live”; must match the secret key.
country kirak.json Two-letter country code of the account; needed for off-session charges.
success_url kirak.json default /payment/success Redirect after a successful payment. Overrides payments.success_url.
KIRAK_PAYMENT_<INSTANCE>_SECRET_KEY environment required Flutterwave secret key (FLWSECK_TEST-… or FLWSECK-…).
KIRAK_PAYMENT_<INSTANCE>_SECRET_HASH environment required Secret hash set on the webhook; verifies webhooks.

mercadopago (no extra install) – Mercado Pago: Checkout Pro payments, subscriptions (preapprovals) and disputes (read-only).

Credential check (check()): GET /users/me.

Name Where Required / default Description
environment kirak.json default sandbox “sandbox” or “production”.
success_url kirak.json default /payment/success Redirect after a successful payment. Overrides payments.success_url.
KIRAK_PAYMENT_<INSTANCE>_ACCESS_TOKEN environment required Mercado Pago access token.
KIRAK_PAYMENT_<INSTANCE>_WEBHOOK_SECRET environment required Secret signature of the webhook; verifies webhooks.

xendit (no extra install) – Xendit Invoices: one-time payments and refunds.

Credential check (check()): GET /balance.

Name Where Required / default Description
environment kirak.json default test “test” or “live”; must match the secret key.
success_url kirak.json default /payment/success Redirect after a successful payment. Overrides payments.success_url.
KIRAK_PAYMENT_<INSTANCE>_SECRET_KEY environment required Xendit secret API key (xnd_development_… or xnd_production_…).
KIRAK_PAYMENT_<INSTANCE>_CALLBACK_TOKEN environment required Callback verification token; verifies webhooks.

airwallex (no extra install) – Airwallex Payment Links: one-time payments, refunds and disputes (read-only).

Credential check (check()): POST /api/v1/authentication/login.

Name Where Required / default Description
environment kirak.json default sandbox “sandbox” or “production”.
KIRAK_PAYMENT_<INSTANCE>_CLIENT_ID environment required Airwallex API client ID.
KIRAK_PAYMENT_<INSTANCE>_API_KEY environment required Airwallex API key.
KIRAK_PAYMENT_<INSTANCE>_WEBHOOK_SECRET environment required Secret of the webhook; verifies webhooks.

omise (no extra install) – Omise (Opn Payments) Links: one-time payments, refunds and disputes (read-only).

Credential check (check()): GET /account.

Name Where Required / default Description
environment kirak.json default test “test” or “live”; must match the secret key.
KIRAK_PAYMENT_<INSTANCE>_SECRET_KEY environment required Omise secret key (skey_test_… or skey_…).
KIRAK_PAYMENT_<INSTANCE>_WEBHOOK_SECRET environment Base64 webhook secret; without it each webhook is verified by reading its event back.

telr (no extra install) – Telr Hosted Payment Page: one-time payments; refunds made in the Telr admin are recorded.

Credential check (check()): None: Telr has no read-only call; the offline checks run.

Name Where Required / default Description
store_id kirak.json required Numeric Telr store ID.
environment kirak.json default test “test” or “live”.
success_url kirak.json required Absolute URL Telr returns the buyer to after paying, declining or cancelling.
KIRAK_PAYMENT_<INSTANCE>_AUTH_KEY environment required Authentication key of the Hosted Payment Page.
KIRAK_PAYMENT_<INSTANCE>_ADVICE_SECRET environment required Secret key of the transaction advice; verifies webhooks.

Requires pip install "kirak[storage]" (image processing, and every S3-compatible type); the gcs and azure types need pip install "kirak[storage-gcs]" or "kirak[storage-azure]" instead, which include it. Providers are declared in kirak.json under "storage" as named instances; only credentials are environment variables (prefix KIRAK_STORAGE_).

{
"storage": {
"default_provider": "local",
"providers": {
"local": { "type": "local", "upload_dir": "assets/media" }
},
"image_allowed_types": "jpg,jpeg,png,webp,gif",
"image_max_size": "5mb",
"image_compress_quality": 85,
"image_max_width": 2000,
"image_max_height": 2000,
"file_allowed_types": "pdf,doc,docx,xls,xlsx,csv,txt,zip",
"file_max_size": "50mb",
"default_thumbnails": null,
"thumbnail_mode": "sync"
}
}
storage key Type Description
default_provider string Instance name used when a call names no provider. Must be one of the instances under providers.
providers object Storage provider instances (types local, aws, wasabi, r2, spaces, cubbit, ovh, b2, gcs, azure, or a custom type), by instance name.
image_allowed_types string Allowed image extensions, comma-separated. Default “jpg,jpeg,png,webp,gif”. svg is refused: store vector files with upload_file.
image_max_size string Maximum image upload size, e.g. “5mb”. Default “5mb”.
image_compress_quality integer JPEG/WebP compression quality. Default 85.
image_max_width integer Maximum stored image width in pixels; larger images are scaled down. Default 2000.
image_max_height integer Maximum stored image height in pixels; larger images are scaled down. Default 2000.
file_allowed_types string Allowed non-image extensions, comma-separated. Default “pdf,doc,docx,xls,xlsx,csv,txt,zip”.
file_max_size string Maximum file upload size, e.g. “50mb”. Default “50mb”.
default_thumbnails string or null Thumbnails generated for every image upload, e.g. “sm:100x100,md:300x300”. Default none.
thumbnail_mode string sync makes thumbnails before responding; background responds first. Default sync.
Every storage operation is also path-scoped under the caller’s user id (except for admin) – see Storage.

Settings go in the provider entry in kirak.json; secrets are environment variables, one set per instance: KIRAK_STORAGE_<INSTANCE>_<FIELD>, upper-cased. Credentials in kirak.json are rejected. aws and wasabi credentials are optional; boto3 uses its default credential chain when they are unset (set both keys or neither). The other S3-compatible types need both keys. gcs and azure credentials are optional too: without them the app’s Google Application Default Credentials or Azure identity is used. A local instance is served at /media/<instance name>; two local instances need different directories.

<INSTANCE> is the provider instance’s name in kirak.json, upper-cased: an instance named main reads ..._MAIN_....

local (no extra install) – Files on the app’s own disk, served at /media/.

Credential check (check()): upload_dir is (or can be created) readable and writable where the check runs.

Name Where Required / default Description
upload_dir kirak.json default assets/media Directory uploads are written to. Two local instances need different ones.

aws (pip install "kirak[storage]") – Amazon S3, or any S3-compatible service through endpoint_url.

Credential check (check()): ListObjectsV2 (MaxKeys=1); with write, PutObject and DeleteObject of one object.

Name Where Required / default Description
aws_bucket kirak.json required Bucket name.
aws_region kirak.json default us-east-1 Bucket region.
endpoint_url kirak.json Custom S3 endpoint; leave unset for AWS.
public_url kirak.json Base URL of returned file URLs, e.g. a CDN or custom domain in front of the bucket. Unset: the bucket’s own URL.
acl kirak.json Canned ACL set on each upload: private or public-read. Unset: none is sent, as buckets with ACLs disabled (the AWS default) require.
KIRAK_STORAGE_<INSTANCE>_ACCESS_KEY environment Access key ID. Optional: boto3’s default credential chain is used when unset.
KIRAK_STORAGE_<INSTANCE>_SECRET_KEY environment Secret access key. Set together with the access key.

wasabi (pip install "kirak[storage]") – Wasabi object storage (S3-compatible).

Credential check (check()): ListObjectsV2 (MaxKeys=1); with write, PutObject and DeleteObject of one object.

Name Where Required / default Description
aws_bucket kirak.json required Bucket name.
aws_region kirak.json default us-east-1 Bucket region.
endpoint_url kirak.json default https://s3.wasabisys.com Wasabi endpoint.
public_url kirak.json Base URL of returned file URLs, e.g. a CDN or custom domain in front of the bucket. Unset: the bucket’s own URL.
acl kirak.json Canned ACL set on each upload: private or public-read. Unset: none is sent, as buckets with ACLs disabled (the AWS default) require.
KIRAK_STORAGE_<INSTANCE>_ACCESS_KEY environment Access key ID. Optional: boto3’s default credential chain is used when unset.
KIRAK_STORAGE_<INSTANCE>_SECRET_KEY environment Secret access key. Set together with the access key.

r2 (pip install "kirak[storage]") – Cloudflare R2 (S3-compatible). Returned URLs are public only through public_url.

Credential check (check()): ListObjectsV2 (MaxKeys=1); with write, PutObject and DeleteObject of one object.

Name Where Required / default Description
account_id kirak.json required Cloudflare account id (32 hex characters); sets the endpoint.
aws_bucket kirak.json required Bucket name.
jurisdiction kirak.json default default Where the bucket’s data is kept: default, eu or fedramp. Must match the bucket.
aws_region kirak.json default auto Leave unset: R2 ignores it.
endpoint_url kirak.json Leave unset: built from account_id and jurisdiction.
public_url kirak.json Base URL of returned file URLs: the bucket’s r2.dev subdomain or a custom domain bound to it. Unset: URLs point at the S3 endpoint, which is never public; use get_url with expires.
acl kirak.json Leave unset: R2 has no object ACLs, so setting it is an error.
KIRAK_STORAGE_<INSTANCE>_ACCESS_KEY environment required Access key ID.
KIRAK_STORAGE_<INSTANCE>_SECRET_KEY environment required Secret access key.

spaces (pip install "kirak[storage]") – DigitalOcean Spaces (S3-compatible).

Credential check (check()): ListObjectsV2 (MaxKeys=1); with write, PutObject and DeleteObject of one object.

Name Where Required / default Description
aws_bucket kirak.json required Space (bucket) name.
aws_region kirak.json required Datacenter region of the Space, e.g. nyc3 or fra1; sets the endpoint.
endpoint_url kirak.json Leave unset: https://<aws_region>.digitaloceanspaces.com.
public_url kirak.json Base URL of returned file URLs, e.g. the Spaces CDN https://..cdn.digitaloceanspaces.com or a custom domain. Unset: https://..digitaloceanspaces.com.
acl kirak.json default public-read Canned ACL set on each upload: public-read (files readable by URL) or private.
KIRAK_STORAGE_<INSTANCE>_ACCESS_KEY environment required Access key ID.
KIRAK_STORAGE_<INSTANCE>_SECRET_KEY environment required Secret access key.

cubbit (pip install "kirak[storage]") – Cubbit DS3, European geo-distributed object storage (S3-compatible).

Credential check (check()): ListObjectsV2 (MaxKeys=1); with write, PutObject and DeleteObject of one object.

Name Where Required / default Description
aws_bucket kirak.json required Bucket name.
aws_region kirak.json default eu-west-1 Signing region.
endpoint_url kirak.json default https://s3.cubbit.eu Cubbit endpoint; https://s3..cubbit.eu for a custom tenant.
public_url kirak.json Base URL of returned file URLs, e.g. a CDN or custom domain in front of the bucket. Unset: the bucket’s own URL.
acl kirak.json Canned ACL set on each upload: private or public-read. Unset: none is sent, as buckets with ACLs disabled (the AWS default) require.
KIRAK_STORAGE_<INSTANCE>_ACCESS_KEY environment required Access key ID.
KIRAK_STORAGE_<INSTANCE>_SECRET_KEY environment required Secret access key.

ovh (pip install "kirak[storage]") – OVHcloud Object Storage (S3-compatible).

Credential check (check()): ListObjectsV2 (MaxKeys=1); with write, PutObject and DeleteObject of one object.

Name Where Required / default Description
aws_bucket kirak.json required Bucket name.
aws_region kirak.json required Region code in lower case, e.g. gra, sbg, de, uk or eu-west-par; sets the endpoint.
endpoint_url kirak.json Leave unset: https://s3.<aws_region>.io.cloud.ovh.net.
public_url kirak.json Base URL of returned file URLs, e.g. a CDN or custom domain. Unset: https://.s3..io.cloud.ovh.net.
acl kirak.json Canned ACL set on each upload: private or public-read. Unset: none is sent (files are private unless a bucket policy makes them public).
KIRAK_STORAGE_<INSTANCE>_ACCESS_KEY environment required Access key ID.
KIRAK_STORAGE_<INSTANCE>_SECRET_KEY environment required Secret access key.

b2 (pip install "kirak[storage]") – Backblaze B2 (S3-compatible).

Credential check (check()): ListObjectsV2 (MaxKeys=1); with write, PutObject and DeleteObject of one object.

Name Where Required / default Description
aws_bucket kirak.json required Bucket name.
aws_region kirak.json required Region of the bucket’s S3 endpoint, e.g. us-west-004; sets the endpoint.
endpoint_url kirak.json Leave unset: https://s3.<aws_region>.backblazeb2.com.
public_url kirak.json Base URL of returned file URLs, e.g. a CDN or the bucket’s friendly URL https://f004.backblazeb2.com/file/. Unset: https://s3..backblazeb2.com/, public when the bucket is.
acl kirak.json Leave unset: B2 sets ACLs per bucket, so setting it is an error.
KIRAK_STORAGE_<INSTANCE>_ACCESS_KEY environment required Application key ID (keyID).
KIRAK_STORAGE_<INSTANCE>_SECRET_KEY environment required Application key (applicationKey).

gcs (pip install "kirak[storage-gcs]") – Google Cloud Storage, with a service account key or Application Default Credentials.

Credential check (check()): objects.list (maxResults=1); with write, objects.insert and objects.delete of one object; under ADC with signing_service_account, IAM signBlob of one URL.

Name Where Required / default Description
bucket kirak.json required Bucket name.
project_id kirak.json Project id. Unset: the key’s project, or the ADC project.
public_url kirak.json Base URL of returned file URLs, e.g. a Cloud CDN or load balancer domain. Unset: https://storage.googleapis.com/, readable only if the bucket grants allUsers read.
signing_service_account kirak.json Service account email that signs URLs (get_url with expires) under Application Default Credentials; the app’s identity needs iam.serviceAccounts.signBlob on it. Not needed with credentials_json.
KIRAK_STORAGE_<INSTANCE>_CREDENTIALS_JSON environment Service account key file contents (JSON). Optional: Application Default Credentials are used when unset.

azure (pip install "kirak[storage-azure]") – Azure Blob Storage, with a connection string, an account key or the app’s Azure identity.

Credential check (check()): List Blobs (maxresults=1); with write, Put Blob and Delete Blob of one blob; under an Azure identity, Get User Delegation Key.

Name Where Required / default Description
container kirak.json required Container name.
account_name kirak.json Storage account name. Required unless connection_string is set.
account_url kirak.json Blob endpoint, for sovereign clouds or Azurite. Unset: https://<account_name>.blob.core.windows.net.
public_url kirak.json Base URL of returned file URLs, e.g. an Azure Front Door or CDN domain. Unset: the blob’s own URL, readable only if the container allows anonymous blob access.
KIRAK_STORAGE_<INSTANCE>_CONNECTION_STRING environment Storage account connection string. Optional: account_name with account_key, or the app’s Azure identity, is used when unset.
KIRAK_STORAGE_<INSTANCE>_ACCOUNT_KEY environment Storage account access key, used with account_name. Optional: without it the app’s Azure identity (DefaultAzureCredential) is used.

The database provider requires no extra install – it uses your existing database. Redis and RabbitMQ providers require optional extras. Providers are declared in kirak.json under "scheduler" as named instances; only connection URLs are environment variables (prefix KIRAK_SCHEDULER_).

{
"scheduler": {
"default_provider": "db",
"providers": {
"db": { "type": "database" }
},
"poll_interval": 5,
"concurrency": 4,
"default_queue": "default",
"queues": ["emails"],
"job_timeout": 3600,
"max_retries": 3,
"retry_backoff": 60
}
}
scheduler key Type Description
default_provider string Instance name used when a call names no provider. Must be one of the instances under providers.
providers object Queue provider instances (types database, redis, rabbitmq, or a custom type), by instance name. At most one database entry.
poll_interval integer Seconds between queue polls (database and redis providers). Default 5.
concurrency integer Maximum jobs run in parallel per provider. Default 4.
default_queue string Queue used when enqueue() is given none. Always consumed. Default “default”.
queues array Extra queues to consume besides default_queue. Default [].
job_timeout integer Seconds a job may run before the worker stops and retries it. Default 3600.
max_retries integer Default maximum retry attempts per job. Default 3.
retry_backoff integer Base delay between retries in seconds, multiplied by the attempt number. Default 60.
At most one database provider. A job still running 60 seconds past job_timeout is treated as orphaned by a crashed worker and put back in the queue.

Settings go in the provider entry in kirak.json; connection URLs are environment variables, one per instance: KIRAK_SCHEDULER_<INSTANCE>_URL, upper-cased. URLs in kirak.json are rejected.

<INSTANCE> is the provider instance’s name in kirak.json, upper-cased: an instance named main reads ..._MAIN_....

database (no extra install) – Queue in the app’s own database. No extra install. At most one per project.

Name Where Required / default Description
table kirak.json default scheduler_jobs Deprecated. Must be scheduler_jobs if set; any other value fails at startup.

redis (pip install "kirak[scheduler-redis]") – Queue in Redis (sorted sets).

Credential check (check()): Connect and PING.

Name Where Required / default Description
redis_ssl kirak.json default False Connect over TLS.
KIRAK_SCHEDULER_<INSTANCE>_URL environment Redis URL. Default redis://localhost:6379.

rabbitmq (pip install "kirak[scheduler-rabbitmq]") – Queue in RabbitMQ.

Credential check (check()): Connect and open a channel.

Name Where Required / default Description
KIRAK_SCHEDULER_<INSTANCE>_URL environment AMQP URL. Default amqp://guest:guest@localhost/.

Requires pip install "kirak[ai-openai]", pip install "kirak[ai-anthropic]", or pip install "kirak[ai-google]" depending on your provider. Models are "provider:model" strings: agents name theirs in the agent file, and default_model in kirak.json is the fallback. Embeddings are configured under vector, not here. API keys are not Kirak settings; each provider SDK reads its own standard environment variable.

{
"ai": {
"default_model": "openai:gpt-4o-mini",
"conversation_ttl_seconds": 3600
}
}
ai key Type Description
default_model string “provider:model” used when an agent or call names no model.
conversation_ttl_seconds integer Seconds a saved agent conversation is kept. Default 3600.
compaction_token_threshold integer or null Token count at which a long conversation is compacted. null turns compaction off. Default 150000.
How compaction works per provider is described in
AI Integration. For the calls that use
these settings, see AI Integration.

The API key variable is read by the provider’s SDK, not by Kirak.

Provider Model prefixes Install API key variable
openai openai:, openai-responses: pip install "kirak[ai-openai]" OPENAI_API_KEY
anthropic anthropic: pip install "kirak[ai-anthropic]" ANTHROPIC_API_KEY
google google-gla:, google: pip install "kirak[ai-google]" GOOGLE_API_KEY, GEMINI_API_KEY

Store and embedding providers for retrieval (RAG); see Vector. Two independent provider sets, each declared like the other modules’ providers. Either may be left out (bring your own vectors and skip embedding), but an enabled module needs at least one.

"vector": {
"store": {
"default_provider": "pine",
"providers": {
"pine": { "type": "pinecone", "cloud": "aws", "region": "us-east-1" },
"s3v": { "type": "s3_vectors", "bucket": "my-vector-bucket", "region": "us-east-1" }
}
},
"embedding": {
"default_provider": "openai",
"providers": {
"openai": { "type": "openai", "model": "text-embedding-3-small" },
"google": { "type": "google", "model": "gemini-embedding-001" },
"local": { "type": "ollama", "model": "nomic-embed-text", "base_url": "http://localhost:11434" }
}
}
}
vector key Type Description
store object Vector store providers (e.g. pinecone, s3_vectors).
embedding object Embedding providers (e.g. openai, google, ollama).
Secrets are read from the environment, one set per instance: KIRAK_VECTOR_STORE_<INSTANCE>_<FIELD> and
KIRAK_VECTOR_EMBEDDING_<INSTANCE>_<FIELD>, upper-cased. Secrets in kirak.json are rejected. AWS credentials for
s3_vectors are optional: boto3’s default credential chain is used when unset (set both keys or neither).

<INSTANCE> is the provider instance’s name in kirak.json, upper-cased: an instance named main reads ..._MAIN_....

store / pinecone (no extra install) – Pinecone serverless indexes.

Credential check (check()): GET /indexes.

Name Where Required / default Description
cloud kirak.json default aws Cloud of new indexes.
region kirak.json default us-east-1 Region of new indexes.
api_version kirak.json default 2026-04 Pinecone API version.
batch_size kirak.json default 100 Vectors per upsert request (at most 1000).
ready_timeout kirak.json default 120 Seconds create_index waits for the index to be ready.
max_retries kirak.json default 3 Retries on rate limits and server errors.
timeout kirak.json default 30.0 Request timeout in seconds.
KIRAK_VECTOR_STORE_<INSTANCE>_API_KEY environment required Pinecone API key.

store / s3_vectors (pip install "kirak[vector-s3vectors]") – Amazon S3 Vectors indexes in an existing vector bucket.

Credential check (check()): GetVectorBucket on the configured bucket.

Name Where Required / default Description
bucket kirak.json required Existing vector bucket.
region kirak.json required Bucket region.
non_filterable_metadata_keys kirak.json Metadata keys stored but not usable in filters, for new indexes.
max_retries kirak.json default 3 Retries on rate limits and server errors.
KIRAK_VECTOR_STORE_<INSTANCE>_ACCESS_KEY_ID environment AWS access key ID. Optional: boto3’s default credential chain is used when unset.
KIRAK_VECTOR_STORE_<INSTANCE>_SECRET_ACCESS_KEY environment AWS secret access key. Set together with the access key ID.

embedding / openai (no extra install) – OpenAI embeddings, or any OpenAI-compatible endpoint through base_url.

Credential check (check()): GET /models; the configured model must be listed.

Name Where Required / default Description
model kirak.json required Embedding model name.
base_url kirak.json default https://api.openai.com/v1 API base URL.
dimensions kirak.json Output vector length, for models that can shorten it.
batch_size kirak.json default 100 Texts per request (at most 2048).
max_retries kirak.json default 3 Retries on rate limits and server errors.
timeout kirak.json default 30.0 Request timeout in seconds.
KIRAK_VECTOR_EMBEDDING_<INSTANCE>_API_KEY environment required OpenAI API key.

embedding / google (no extra install) – Google Gemini embeddings.

Credential check (check()): GET /models/.

Name Where Required / default Description
model kirak.json required Embedding model name.
dimensions kirak.json Output vector length, for models that can shorten it.
batch_size kirak.json default 100 Texts per request (at most 100).
max_retries kirak.json default 3 Retries on rate limits and server errors.
timeout kirak.json default 30.0 Request timeout in seconds.
KIRAK_VECTOR_EMBEDDING_<INSTANCE>_API_KEY environment required Gemini API key.

embedding / ollama (no extra install) – Embeddings from a local or self-hosted Ollama server.

Credential check (check()): GET /api/tags; the configured model must be pulled.

Name Where Required / default Description
model kirak.json required Embedding model name.
base_url kirak.json default http://localhost:11434 Ollama server URL.
batch_size kirak.json default 100 Texts per request.
max_retries kirak.json default 3 Retries on rate limits and server errors.
timeout kirak.json default 30.0 Request timeout in seconds.

Requires pip install "kirak[redis]".

Variable Description
KIRAK_REDIS_URL Redis connection URL. When set, three DB-backed auth utilities are transparently replaced with Redis equivalents: rate limiting (sliding-window sorted set), token blacklist (per-key TTL), and OTP storage (per-key TTL). When not set, the database is used for all three.

URL formats:

KIRAK_REDIS_URL=redis://localhost:6379 # no auth
KIRAK_REDIS_URL=redis://:password@host:6379 # with password
KIRAK_REDIS_URL=rediss://host:6380 # TLS (note: rediss://)

What changes:

Feature Without Redis With Redis
Rate limiting (CRUD and auth endpoints) DB fixed-window (kirak_rate_limits table) Redis sliding-window (more accurate, auto-expires)
Token blacklist DB row (auth_token_blacklist table) Redis key + per-token TTL (auto-cleaned)
OTP storage DB row (auth_otp table) Redis key + OTP expiry TTL (auto-cleaned)

Redis utilities fail open: if Redis becomes unreachable, the request is allowed through rather than returning an error.


The hook timeout, the log directory and the bulk chunk size are hook_timeout_seconds, log_path and bulk_chunk_size in kirak.json; the environment variables KIRAK_HOOK_TIMEOUT, LOG_PATH and KIRAK_BULK_CHUNK_SIZE are no longer read. bulk_chunk_size (default 500) is the maximum number of records per chunk for bulk create, update, delete, and destroy operations; reduce it if you hit database packet-size limits.


Requires pip install "kirak[mcp]" (Python 3.10+). Enable with "modules": ["mcp"] in kirak.json; there are no other kirak.json settings and no environment variables. Each server is a JSON file in mcp/, described by .kirak/mcp.schema.json (kirak schema): name, description, instructions, access, rate_limit_per_minute and a tools map keyed by ref ("orders.fetch": {}). See MCP Servers.


base_url and project_name are settings in kirak.json, not environment variables. base_url (for example https://api.example.com) is used to build links in auth emails (verification, password reset) and social login callbacks.


Besides the provider secrets listed per module above. kirak env lists the ones a project needs, given its kirak.json, and whether each is set.

Variable Read by Required Secret Purpose
DB_PASSWORD core yes Database password; every other database setting is in kirak.json “database”.
KIRAK_REDIS_URL core yes Redis URL. When set, rate limiting, the token blacklist, OTP storage and model caching use Redis instead of the database.
KIRAK_AUTH_JWT_SECRET_KEY auth yes yes Signs access tokens (at least 32 bytes). Also the fallback of the other auth secrets.
KIRAK_AUTH_JWT_REFRESH_SECRET_KEY auth yes Signs refresh tokens. Default: KIRAK_AUTH_JWT_SECRET_KEY; set a separate one in production.
KIRAK_AUTH_JWT_OLD_SECRET_KEY auth yes Previous access-token key, during a key rotation, so tokens it signed stay valid until they expire.
KIRAK_AUTH_JWT_REFRESH_OLD_SECRET_KEY auth yes Previous refresh-token key, during a key rotation. Default: KIRAK_AUTH_JWT_OLD_SECRET_KEY.
KIRAK_AUTH_VERIFICATION_KEY auth yes yes Fernet key signing email verification and password reset links.
KIRAK_AUTH_ENCRYPTION_KEY auth yes Key encrypting social login tokens and MFA secrets. Default: derived from KIRAK_AUTH_JWT_SECRET_KEY, with a warning; set it in production.
KIRAK_AUTH_WEB_TOKEN_SECRET auth yes Signs short-lived Apple web sign-in state tokens. Default: KIRAK_AUTH_JWT_SECRET_KEY.
KIRAK_AUTH_API_KEY_SECRET auth yes Keys the stored hash of API keys, so rotating KIRAK_AUTH_JWT_SECRET_KEY does not invalidate them. Default: KIRAK_AUTH_JWT_SECRET_KEY; set it in production. Keys created before it was set keep working until the JWT secret changes.
KIRAK_MONITORING_INGESTION_KEY monitoring yes Bearer token required on every /monitoring/* endpoint except /monitoring/ping. Unset: those endpoints answer 503.
KIRAK_MONITORING_LOG_SHIP_SECRET monitoring yes Bearer token sent with the log batches posted to monitoring.log_ship_url.

# Secrets only. Database host and name, base URL, CORS origins, branding and
# social client IDs are in kirak.json.
# -- Database ------------------------------------------------------
DB_PASSWORD=
# -- Auth (required) -----------------------------------------------
KIRAK_AUTH_JWT_SECRET_KEY=replace-with-32-byte-or-longer-secret
KIRAK_AUTH_JWT_REFRESH_SECRET_KEY=another-32-byte-or-longer-secret
KIRAK_AUTH_VERIFICATION_KEY=your-fernet-key-here
KIRAK_AUTH_ENCRYPTION_KEY=your-hex-key-here
# token lifetimes, bcrypt_rounds and password_complexity are kirak.json "auth" settings, not env vars
# -- Social auth secrets -- set only the providers you use ----------
# (client IDs and redirect URIs are kirak.json -> auth.social)
# KIRAK_AUTH_GOOGLE_CLIENT_SECRET=
# KIRAK_AUTH_GITHUB_CLIENT_SECRET=
# -- Notifications (credentials only -- provider/host/sender are kirak.json) --
# KIRAK_NOTIFICATION_EMAIL_AWS_SES_ACCESS_KEY= # instance named "aws_ses"
# KIRAK_NOTIFICATION_EMAIL_AWS_SES_SECRET_KEY=
# -- Payments --------------------------------------------------------
# KIRAK_PAYMENT_STRIPE_SECRET_KEY=sk_live_...
# KIRAK_PAYMENT_STRIPE_WEBHOOK_SECRET=whsec_...
# -- Storage (credentials only -- backend/dir are kirak.json) --------
# KIRAK_STORAGE_MAIN_ACCESS_KEY= # instance named "main" (aws, wasabi, r2, spaces, cubbit, ovh, b2)
# KIRAK_STORAGE_MAIN_SECRET_KEY=
# KIRAK_STORAGE_GCS_CREDENTIALS_JSON= # instance named "gcs" (unset: Application Default Credentials)
# KIRAK_STORAGE_BLOBS_CONNECTION_STRING= # instance named "blobs" (azure), or ..._ACCOUNT_KEY
# -- Scheduler (connection only -- providers/concurrency are kirak.json) --
# KIRAK_SCHEDULER_REDIS_URL=redis://localhost:6379
# -- AI (API keys only -- provider/model are kirak.json) -------------
# OPENAI_API_KEY=sk-...
# -- Vector (credentials only -- providers/models are kirak.json) ----
# KIRAK_VECTOR_STORE_PINE_API_KEY= # store instance named "pine"
# KIRAK_VECTOR_EMBEDDING_OPENAI_API_KEY= # embedding instance named "openai"
# -- Redis (optional -- enables sliding-window rate limit, etc.) ----
# KIRAK_REDIS_URL=redis://localhost:6379
// kirak.json -- non-secret settings for the modules above
{
"modules": ["notifications", "payments", "storage", "scheduler", "ai"],
"notifications": {
"email_from_address": "no-reply@example.com",
"email": { "default_provider": "ses", "providers": { "ses": { "type": "aws_ses" } } }
},
"storage": {
"default_provider": "local",
"providers": { "local": { "type": "local", "upload_dir": "assets/media" } }
},
"scheduler": {
"default_provider": "db",
"providers": { "db": { "type": "database" } },
"concurrency": 4
},
"ai": { "default_model": "openai:gpt-4o-mini" }
}