Quickstart
You will issue a sandbox key, make an authenticated request, and receive a webhook. Budget about five minutes.
1. Issue a test key
In the MineTech portal, go to Developers → API Keys, keep the environment on sandbox, and create a key.
You are shown two values, once:
| Value | Looks like | Used for |
|---|---|---|
| API key | mt_test_j4k2m… | Authenticating every request |
| Signing secret | 64 hex characters | Signing requests, when the key requires it |
Store both before closing the dialog — neither can be retrieved afterwards. If you lose one, rotate the key. The dialog offers a Download credentials file if you want a machine-readable copy.
A mt_test_… key reaches a separate dataset and cannot touch production records.
Request signing is off by default for test keys and on for live keys, so you can
get something working first and harden second.
2. Make a request
- Node SDK
- cURL
- Python
npm install @minetech/node
import { MineTech } from '@minetech/node';
const client = new MineTech({ apiKey: process.env.MINETECH_API_KEY! });
const lots = await client.operations.lots.list({ limit: 5 });
console.log(lots.items);
curl https://sandbox.api.minetech.rw/v1/operations/lots?limit=5 \
-H "Authorization: Bearer $MINETECH_API_KEY"
# The Python SDK is in development. Use the REST API directly for now.
import os, urllib.request, json
request = urllib.request.Request(
"https://sandbox.api.minetech.rw/v1/operations/lots?limit=5",
headers={"Authorization": f"Bearer {os.environ['MINETECH_API_KEY']}"},
)
with urllib.request.urlopen(request) as response:
print(json.load(response))
A 401 here almost always means the key was truncated on copy. A 403 means the
key is valid but lacks the scope for that resource — check Developers → API
Keys → Scopes.
3. Discover what your key can do
Scopes are published by the API itself, so you never have to guess or hardcode a list:
const groups = await client.developer.listScopes();
for (const group of groups) {
console.log(group.label, group.scopes.map((s) => s.scope));
}
Scopes are <resource>.<verb> where verb is read, write or delete. Note that
write does not imply read — a write-only ingestion key deliberately cannot
read the dataset back. See Scopes and tenancy.
4. Receive a webhook
Register a receiver so MineTech can push changes to you instead of you polling.
Start the reference receiver:
git clone https://github.com/minetech/minetech.git
cd minetech/sdk-service/examples/express-webhooks
pnpm install
MINETECH_WEBHOOK_SECRET=whsec_… node server.mjs
Expose it (ngrok http 3000), then in Developers → Webhooks add the public URL
with environment sandbox and select the events you want. Press Send test
ping — the receiver logs it immediately.
import { constructEvent } from '@minetech/node/webhooks';
// `req.body` MUST be the raw bytes: express.raw({ type: 'application/json' }).
const event = await constructEvent({
payload: req.body,
signatureHeader: req.header('x-mt-signature'),
secret: process.env.MINETECH_WEBHOOK_SECRET!,
});
The signature covers the exact bytes we sent. express.json() parses the body, and
re-serialising it changes key order and number formatting, so verification fails on
every delivery. This is the single most common webhook integration mistake.
5. Go live
When you are ready:
- Create a live key. Signing is on by default — pass the signing secret to the SDK and it is handled for you. See Request signing.
- Register a live webhook endpoint. Live endpoints must be
httpsand publicly routable;localhostand private addresses are rejected. - Optionally restrict the key to your egress addresses under Developers → IP Allowlist.
Next
- Authentication — keys, signing, and what each error means
- Errors — the error contract and how to handle each class
- Idempotency — why retrying a write is safe
- Core API reference — every endpoint