Get API Credentials
Step 1 of 4 — You need API keys to authenticate requests to the Miracle API. This page explains how to get them and how authentication works.
API key types
Every API key is a pair — a secret key and a publishable key, generated together. A third credential type, the client secret, is generated per checkout session. Each credential serves a different purpose:
| Credential | Format | Use | Where |
|---|---|---|---|
| Secret key | sk_test_... / sk_live_... | Authenticates server-side API requests (payments, refunds, sessions) | Your backend only |
| Publishable key | pk_test_... / pk_live_... | Identifies your account in client-side flows (tokenization, payment methods) | Frontend JS, mobile apps |
| Client secret | Opaque token (returned when creating a checkout session) | Authenticates HPP/widget flows — scoped to a single checkout session | HPP, payment widget |
Test vs. live keys
Each key pair belongs to an environment:
| Environment | Key prefix | Behavior |
|---|---|---|
| Test | sk_test_, pk_test_ | Sandbox only — no real money moves. Use these during development. |
| Live | sk_live_, pk_live_ | Production — processes real payments. Use these only after you go live. |
The environment is determined server-side from the key prefix. You do not need to pass an environment parameter in your requests.
Get your keys
- Log in to the Miracle Portal and switch it to the mode you need: test mode issues test keys (
sk_test_,pk_test_), live mode issues live keys. - Open API Keys in the sidebar and choose Create key.
- Choose the key type: a secret key for server-side calls, or a public key for tokenization in the browser.
- Give the key a descriptive name, for example "Backend, staging" or "Mobile app". If you manage more than one merchant, choose the merchant the key belongs to.
- For a secret key, select the permissions it needs. A key carries only the permissions selected for it: a key with none authenticates but cannot call anything. For the hosted payment page, select at least
payment-experience:checkout:createandpayment-experience:checkout:view; for payments created directly through the API,payment-processing:transaction:createandpayment-processing:transaction:view. - Optionally limit the key to IP ranges and set an expiry, check the summary, and choose Create and reveal.
- Copy the key the wizard shows.
Your secret key is shown only once. Copy it immediately and store it somewhere secure. If you lose it, rotate the key in the Portal to get a new secret.
Authentication
All API requests are authenticated with a Bearer token in the Authorization header. Use your secret key for server-side calls. In the examples, replace <api-host> with the API host your operator gave you:
curl https://<api-host>/v1/payments \
-H "Authorization: Bearer sk_test_your_secret_key" \
-H "Content-Type: application/json"const response = await fetch('https://<api-host>/v1/payments', {
headers: {
'Authorization': `Bearer ${process.env.MIRACLE_SECRET_KEY}`,
'Content-Type': 'application/json',
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://<api-host>/v1/payments",
headers={
"Authorization": f"Bearer {os.environ['MIRACLE_SECRET_KEY']}",
"Content-Type": "application/json",
},
)
data = response.json()["data"]When to use which credential
| Scenario | Credential to use |
|---|---|
| Create a payment from your server | sk_test_ / sk_live_ |
| Create a refund | sk_test_ / sk_live_ |
| Create an HPP checkout session | sk_test_ / sk_live_ |
| Tokenize a card from your frontend | pk_test_ / pk_live_ |
| Fetch available payment methods from your frontend | pk_test_ / pk_live_ |
| Tokenize, fetch payment methods, or pay within HPP/widget | Client secret |
Publishable keys only grant access to the /tokenize and /payment-methods endpoints. Client secrets additionally grant access to /payments, but only for the associated checkout session. Any other endpoint will return 403 Forbidden.
Origin restrictions for publishable keys. Live publishable keys (pk_live_*) validate the request origin against the allowed origins configured on your merchant account. Requests from unregistered origins are rejected with 403 Forbidden. Test publishable keys (pk_test_*) skip this check so you can develop freely from any origin, including localhost.
Idempotency
All write operations (POST, PATCH, DELETE) require an Idempotency-Key header. This lets you safely retry requests without creating duplicate side-effects (e.g., double-charging a customer).
Idempotency-Key: your-unique-request-idUse a unique value per request — a UUID v4 works well. The API will return the same response for repeated calls with the same idempotency key.
Key lifecycle
API keys have three possible states:
| State | Description |
|---|---|
| Active | Key is usable for API requests. |
| Revoked | Manually revoked. Stops working within 30 seconds; irreversible. |
| Expired | Past its expiration date (if one was set at creation). |
To rotate a key, select it in the Portal and choose Rotate, or call POST /v1/api-keys/{id}/rotate with an Idempotency-Key. You get a new secret with the same name, permissions and restrictions, shown once. The old key keeps working for a grace period (24 hours from the Portal; through the API, graceHours from 0 to 720), so you can switch your application without downtime. Keys never rotate on their own.
While your merchant account, or the account of the operator above it, is suspended or disabled, every key you hold answers 401 Unauthorized, test keys included, and no key can be created or rotated (409 CONFLICT). The same keys work again once the account is reinstated.
Security best practices
Protect your secret keys. Compromised keys can be used to create payments, issue refunds, and access transaction data on your account.
- Never expose secret keys in client-side code. Do not include
sk_keys in JavaScript bundles, mobile apps, or HTML. Use publishable keys (pk_) for client-side calls. - Store keys in environment variables, not in source code or version control.
- Use test keys for development. Switch to live keys only when you are ready to process real payments.
- Act immediately if you suspect a key has been compromised: revoke it and issue a new one, or rotate it through the API with
"graceHours": 0so the old key stops working within 30 seconds. - Restrict permissions when a key does not need full API access. For example, a key used only for creating payments does not need refund permissions.
Next step
You have your API keys — now create your first payment.