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.
- Navigate to Settings > API Keys.
- Click Create API Key.
- Give the key a descriptive name (e.g., "Backend — staging" or "Mobile app").
- Copy both the publishable key and the secret key.
Your secret key is shown only once. Copy it immediately and store it somewhere secure. If you lose it, you will need to create a new key pair.
You can optionally restrict the key to a subset of permissions. If you leave permissions unrestricted, the key inherits the full scope of its owner.
Authentication
All API requests are authenticated with a Bearer token in the Authorization header. Use your secret key for server-side calls:
curl https://api.miracle.com/v1/payments \
-H "Authorization: Bearer sk_test_your_secret_key" \
-H "Content-Type: application/json"const response = await fetch('https://api.miracle.com/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.miracle.com/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. Immediate and irreversible. |
| Expired | Past its expiration date (if one was set at creation). |
To rotate a key: create a new key pair, update your application, verify it works, then revoke the old key. There is no automatic rotation.
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.
- Rotate keys immediately if you suspect they have been compromised. Create a new pair, deploy it, then revoke the old key.
- 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.