API Quickstart
This is the code-first path. If you’d rather see the same loop in the UI first, the Spam Classifier tutorial covers the same ground through the console.
You need a Nyckel account and a clientId / clientSecret pair. Both are in the
Access Management section of your account, and on the Integrate tab of any function.
1. Get an access token
Every API request carries a bearer token. Tokens come from connect/token, which sits outside the
/v1/ API surface.
curl -X POST 'https://www.nyckel.com/connect/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials&client_id=<clientId>&client_secret=<clientSecret>'
{
"access_token": "<accessToken>",
"token_type": "Bearer",
"expires_in": 3600
}
Tokens are valid for one hour. Request a new one when it expires — see Authentication for rotation details.
export NYCKEL_TOKEN='<accessToken>'
2. Create a function
A function is the whole unit: endpoint, model, sample store, and review queue. You pick its input
modality (Text, Image, or Tabular) and its output modality at creation time. Both are
immutable — a function that classifies text can’t later be switched to images.
curl -X POST 'https://www.nyckel.com/v1/functions' \
-H "Authorization: Bearer $NYCKEL_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"name": "sms-spam-classifier",
"input": "Text",
"output": "Classification"
}'
{
"id": "<functionId>",
"name": "sms-spam-classifier",
"input": "Text",
"output": "Classification"
}
export NYCKEL_FN='<functionId>'
3. Define the labels
Labels are the decision space — the set of answers the function is allowed to give. Create one call per label.
curl -X POST "https://www.nyckel.com/v1/functions/$NYCKEL_FN/labels" \
-H "Authorization: Bearer $NYCKEL_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "name": "Spam" }'
curl -X POST "https://www.nyckel.com/v1/functions/$NYCKEL_FN/labels" \
-H "Authorization: Bearer $NYCKEL_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "name": "Not spam" }'
That’s the whole setup. You have not uploaded a single training example, and the function is already callable.
4. Invoke it
curl -X POST "https://www.nyckel.com/v1/functions/$NYCKEL_FN/invoke?externalId=msg-001" \
-H "Authorization: Bearer $NYCKEL_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "data": "WINNER!! Claim your prize now, text CLAIM to 80086" }'
{
"labelName": "Spam",
"labelId": "<labelId>",
"confidence": 0.94,
"externalId": "msg-001"
}
This first prediction is zero-shot — it comes from a foundation model reasoning about your label names, not from a model trained on your data. For plenty of use cases the zero-shot accuracy is good enough to ship on. See How functions work for what happens underneath.
Two parameters worth knowing now:
| Parameter | Why it matters |
|---|---|
externalId |
Your own id for this input. It comes back on the response, rides along if the invoke is captured for review, and deduplicates the labeled sample you may submit later (step 5) — all without storing anything Nyckel-specific. |
capture |
Defaults to true, which makes the invoke eligible for invoke capture — Nyckel selectively saves the most informative invokes to the review queue. Set capture=false for traffic you never want captured. |
confidence is a calibrated 0.0–1.0 score. It’s what you branch on in production — see
Tuning confidence thresholds.
5. Feed back the correct label
This is the step that makes a function improve. An invoke is not stored as a training sample —
invoke capture selectively queues some invokes for console
review, but your code shouldn’t count on any particular invoke being there. When your application
learns the true label, submit the input together with that label as a new sample, reusing the
externalId:
curl -X POST "https://www.nyckel.com/v1/functions/$NYCKEL_FN/samples" \
-H "Authorization: Bearer $NYCKEL_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"data": "WINNER!! Claim your prize now, text CLAIM to 80086",
"externalId": "msg-001",
"annotation": { "labelName": "Not spam" }
}'
If a sample with the same content or externalId already exists — earlier feedback from you, or a
captured invoke that was annotated in the console — the call returns 409 Conflict carrying the
existing sample’s id. Update that sample’s annotation instead:
curl -X PUT "https://www.nyckel.com/v1/functions/$NYCKEL_FN/samples/<sampleId>/annotation" \
-H "Authorization: Bearer $NYCKEL_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "labelName": "Not spam" }'
Annotations feed the retraining pipeline. Nyckel retrains as they accumulate, benchmarks the new model against the current one, and promotes it only if it scores better. You don’t trigger any of that.
The loop, in one picture
- 1POST /invoke
- 2labelName + confidence
- 3your application acts
- 4POST labeled sample
- 5model retrains
Steps 4 and 5 are the whole production pattern. Everything else in the API — sample sets, function summaries, field management — exists to support that loop at scale.
Finding invokes worth reviewing
Nyckel is already picking review candidates for you: invoke capture
sets aside the invokes most likely to improve the model — low-confidence predictions plus a random
slice of traffic. Annotate them in the console’s Review tab, or pull the queue into your own
annotation workflow (note the v0.9 prefix):
curl "https://www.nyckel.com/v0.9/functions/$NYCKEL_FN/captures?batchSize=20" \
-H "Authorization: Bearer $NYCKEL_TOKEN"
Each item carries the input, the predicted label and confidence, the reason it was captured, and
the externalId you sent on the invoke. Label the ones worth fixing and feed them back exactly as
in step 5. Your own prediction log is the other good source — you know which invokes mattered to
your application, so pick the ones to relabel and submit those.
Next
- Build a feedback loop — wiring step 5 into a real application.
- Production integration patterns — where the invoke call belongs in your request path.
- Function types — detection, search, and OCR, when classification isn’t the right shape.
- Structured data functions — classifying rows of fields instead of a single input.
- API Reference — every endpoint, with auth, errors, and throttling.