Handle requests
Learn what Varis sends to your endpoint, how to verify it, and what your endpoint must return to get paid.
When an agent calls your service, Varis sends a signed request to your endpoint. Your endpoint checks the signature, does its work, and returns a response that satisfies your I/O contract.
Verifying without an SDK
If you don't use TypeScript, verify the signature yourself. For more information, see Verify signatures without an SDK.
What Varis sends
Varis sends one HTTP request to your endpoint URL, with the method you published.
GET: the input arrives in the query string, such as?from=USD&to=EUR&amount=100. There's no body.POST: the input arrives as a JSON body, withContent-Type: application/json.
Varis validates the input against your I/O contract before it engages your servers, so your endpoint receives only well-formed input.
For GET services, numbers and booleans still arrive as strings, so parse them.
Every request carries these headers:
| Header | Description |
|---|---|
X-Varis-Request-Id | A unique ID for the call. Log it, so that you can match your logs to the call in the dashboard. |
X-Varis-Signature | The signature that verifyRequest checks. |
X-Varis-Timestamp | When Varis signed the request. |
X-Varis-Key-Id | The Varis signing key that signed the request. |
Verify the request
Call verifyRequest before you do any work. It returns true if the request comes from Varis, and false otherwise.
import { Varis, VarisKeyFetchError } from "@usevaris/sdk";
const varis = new Varis();
export async function POST(request: Request) {
try {
if (!(await varis.verifyRequest(request))) {
return new Response("Unauthorized", { status: 401 });
}
} catch (error) {
if (error instanceof VarisKeyFetchError) {
return new Response("Service unavailable", { status: 503 });
}
throw error;
}
const { from, to, amount } = await request.json();
const rate = await getRate(from, to);
return Response.json({ rate, converted: amount * rate });
}Follow these rules when you use verifyRequest:
- Create one
Varisinstance per process, at the top of the file or in a shared module. Each instance caches the Varis signing keys, so a new instance per request fetches them every time. - Verify before anything reads the body. Body parsers such as
express.json()consume the body, and the signature check then fails. ForPOSTroutes, callverifyRequestfirst, or skip the body parser on that route. - Return
503, not401, if the keys can't load.verifyRequestthrowsVarisKeyFetchErroronly when it can't fetch the signing keys. That's a temporary problem on your side, not a bad request. - Keep your server clock in sync. Varis rejects requests signed more than 300 seconds before or after your server's time.
The signature covers the method, path, query string, and body, but not the host. A proxy that changes the host is fine.
A proxy or middleware that rewrites the path or query, such as one that strips a prefix, breaks the signature.
Decide what a Varis request can access
A request from Varis comes from an agent, not from one of your own users. It carries no user session and no user ID.
Treat it as its own kind of caller. Don't let it fall through to logic that assumes a signed-in user, and don't give it access to user data unless the service is built for that.
Return a response
To complete the call, return the following:
- A
2xxstatus code. - A JSON body that matches your I/O contract.
Varis checks your response against your contract. If it matches, Varis passes the output to the agent, and you earn.
The call fails, and the agent isn't charged, in any of these cases:
| What happened | Example |
|---|---|
Non-2xx status code | Your endpoint returns 500 or 404. |
| Redirect | Your framework adds a trailing slash and returns 308. Varis never follows redirects. |
| Timeout | Your endpoint takes longer than 30 seconds to respond. |
| Output doesn't match | A required field is missing, a field has the wrong type, or the body is empty or HTML. |
If your service returns HTML, stringify it and pass it into a json response. E.g. {html_response: "<html>...</html>"}
To see why a call failed, open the service in Services and click the request. The Failure reason shows what went wrong.
Test your endpoint locally
To send a signed test request to your endpoint on localhost before you publish, use varis test. For more information, see Local development.