Time-stamps (RFC 3161)
POSThttps://api.kennmarq.com/v1/tsa/{key}
Our own RFC 3161 time-stamp server, for local mode: when your machine signs a C2PA manifest, it asks this URL to time-stamp the signature. The key sits in the URL because the C2PA library can't add headers.
A tsa-only key
Create a key whose only scope is tsa and put it in the URL. Any key with more scopes is refused here with 403 key_not_allowed_in_url: URLs end up in logs, and a powerful key must never be one of them. If that happens, rotate the key you sent.
https://api.kennmarq.com/v1/tsa/sk_live_…Request
Content-Type: application/timestamp-query- The body: a DER-encoded
TimeStampReq, at most 4 KB. - Message imprints in SHA-256, SHA-384 or SHA-512. A SHA-1 imprint gets a rejection status inside the reply.
certReqis honoured (our TSA chain goes into the token) and your nonce is echoed.
Response
200 with Content-Type: application/timestamp-reply exactly, and the DER TimeStampResp as the body, byte for byte as our server produced it. Each token states an accuracy of 1 second, carries a random 128-bit serial and our own policy OID, and is signed with ECDSA P-256 / SHA-256 includingsigningCertificateV2 (RFC 5816).
Every token goes into our public transparency log before it's returned; the X-Log-Index header says where, and GET /v1/log/proof/{index} proves it. A rejection carries no token and no index.
Example with OpenSSL
# A query for a file's SHA-256, asking for our certificate in the reply
openssl ts -query -data artwork.png -sha256 -cert -out request.tsq
curl https://api.kennmarq.com/v1/tsa/$TSA_KEY \
-H "Content-Type: application/timestamp-query" \
--data-binary @request.tsq \
-o response.tsr
openssl ts -reply -in response.tsr -textTo verify a token, fetch our TSA chain from GET /v1/certificate?chain=tsa.
Counting
Each time-stamp counts once in the month's time-stamp allowance, which is the same size as your plan's marks (and your test marks for test keys), kept apart for live and test keys. A request that fails on our side isn't counted. The plan's calls a minute apply to the organisation, all its keys together; the key's IP allowlist applies to the key.
timeStamp.untrusted until our publicly trusted certificate is in place, as they did DigiCert's free stamps. The file still validates.Errors
| Status | Code | When |
|---|---|---|
| 400 | invalid_request | An empty body, or a query our server couldn't parse. |
| 401 | missing_api_key, invalid_api_key, api_key_revoked | No key, an unknown key, or a revoked one. |
| 402 | quota_exceeded | The month's time-stamps are used up. |
| 403 | key_not_allowed_in_url | The key has scopes beyond tsa. |
| 403 | ip_not_allowed | The address isn't on the key's IP allowlist. |
| 413 | payload_too_large | The query is over 4 KB. |
| 415 | unsupported_media_type | The Content-Type isn't application/timestamp-query. |
| 429 | rate_limited | Too many calls this minute. |
| 503 | tsa_unavailable | The time-stamp server is down for a moment. Nothing is charged; retry. |