API Reference
The SourceSeal REST API provides endpoints for submitting and querying attestations. Base URL: http://localhost:8080 (development).
Authentication
All endpoints under /api/v1/ require an API key unless running in development mode. Provide the key via:
Authorization: Bearer <api-key>
# or
X-API-Key: <api-key>Rate Limiting
- Read endpoints (GET): 100 requests/minute per IP
- Write endpoints (POST): 20 requests/minute per IP
/healthzCheck that the server is running and responsive. No authentication required.
Response
{
"status": "ok"
}Status Codes
| Code | Description |
|---|---|
200 OK | Server is healthy |
Example
curl http://localhost:8080/healthz/api/v1/attestationsSubmit a signed attestation for a software artifact. The server verifies the Ed25519 signature before accepting the attestation and anchoring it on the blockchain ledger.
Request Body
{
"attestation": {
"artifact_hash": "sha256-hex-digest-64-chars",
"ecosystem": "npm",
"package_name": "@scope/my-package",
"package_version": "1.2.3",
"sbom_hash": "sha256-hex-digest-64-chars",
"signer_key_id": "hex-key-id",
"signature": "hex-encoded-ed25519-signature",
"slsa_level": 3,
"timestamp": 1700000000
},
"sbom": "<base64-encoded-sbom-bytes>",
"public_key": "-----BEGIN SOURCESEAL ED25519 PUBLIC KEY-----\n...\n-----END SOURCESEAL ED25519 PUBLIC KEY-----"
}Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
attestation.artifact_hash | string | Yes | SHA-256 hex digest (64 chars) of the artifact |
attestation.ecosystem | string | Yes | Package ecosystem identifier (npm, pip) |
attestation.package_name | string | Yes | Full package name |
attestation.package_version | string | No | Package version string |
attestation.signer_key_id | string | Yes | Hex-encoded key ID (SHA-256 of public key, first 16 bytes) |
attestation.signature | string | Yes | Hex-encoded Ed25519 signature |
attestation.timestamp | integer | Yes | Unix timestamp of attestation creation |
public_key | string | Yes | PEM-encoded Ed25519 public key for signature verification |
sbom | bytes | No | Base64-encoded SBOM document |
Response (Success)
{
"id": "hex-attestation-id",
"tx_id": "fabric-transaction-id"
}Status Codes
| Code | Description |
|---|---|
201 Created | Attestation accepted and anchored on the ledger |
400 Bad Request | Invalid body, missing fields, or signature verification failed |
401 Unauthorized | Missing or invalid API key |
429 Too Many Requests | Write rate limit exceeded |
500 Internal Server Error | Storage or ledger submission failure |
Example
curl -X POST http://localhost:8080/api/v1/attestations \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{
"attestation": {
"artifact_hash": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
"ecosystem": "npm",
"package_name": "@myorg/my-package",
"package_version": "1.0.0",
"signer_key_id": "abcdef0123456789abcdef0123456789",
"signature": "deadbeef...",
"slsa_level": 3,
"timestamp": 1700000000
},
"public_key": "-----BEGIN SOURCESEAL ED25519 PUBLIC KEY-----\nMCowBQYDK2VwAyEA...\n-----END SOURCESEAL ED25519 PUBLIC KEY-----"
}'/api/v1/verify/{hash}Look up an attestation by the artifact's SHA-256 hash and verify it against the blockchain ledger.
Path Parameters
| Parameter | Description |
|---|---|
hash | SHA-256 hex digest (exactly 64 lowercase hex characters) |
Response (Verified)
{
"verified": true,
"attestation": {
"id": "hex-attestation-id",
"artifact_hash": "a1b2c3d4...",
"ecosystem": "npm",
"package_name": "@myorg/my-package",
"package_version": "1.0.0",
"signer_key_id": "abcdef01...",
"signature": "deadbeef...",
"slsa_level": 3,
"timestamp": 1700000000
},
"tx_id": "fabric-tx-id",
"timestamp": 1700000100
}Status Codes
| Code | Description |
|---|---|
200 OK | Attestation found. Check the verified field for ledger confirmation. |
400 Bad Request | Invalid hash format |
401 Unauthorized | Missing or invalid API key |
404 Not Found | No attestation found for the given hash |
429 Too Many Requests | Read rate limit exceeded |
Example
curl http://localhost:8080/api/v1/verify/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2 \
-H "Authorization: Bearer your-api-key"/api/v1/attestations?package={name}Retrieve all attestations associated with a given package name.
Query Parameters
| Parameter | Required | Description |
|---|---|---|
package | Yes | The package name to search for |
Response
[
{
"id": "hex-attestation-id-1",
"artifact_hash": "a1b2c3d4...",
"ecosystem": "npm",
"package_name": "@myorg/my-package",
"package_version": "1.0.0",
"signer_key_id": "abcdef01...",
"signature": "deadbeef...",
"slsa_level": 3,
"timestamp": 1700000000
}
]Status Codes
| Code | Description |
|---|---|
200 OK | Query successful (may return an empty array) |
400 Bad Request | Missing package query parameter |
401 Unauthorized | Missing or invalid API key |
429 Too Many Requests | Read rate limit exceeded |
500 Internal Server Error | Failed to query the attestation store |
Example
curl "http://localhost:8080/api/v1/attestations?package=@myorg/my-package" \
-H "Authorization: Bearer your-api-key"/api/v1/attestations/{id}Retrieve a single attestation by its server-generated ID.
Path Parameters
| Parameter | Description |
|---|---|
id | Attestation ID (16-64 lowercase hex characters) |
Response
{
"id": "hex-attestation-id",
"artifact_hash": "a1b2c3d4e5f6...",
"ecosystem": "npm",
"package_name": "@myorg/my-package",
"package_version": "1.0.0",
"sbom_hash": "f6e5d4c3b2a1...",
"signer_key_id": "abcdef0123456789...",
"signature": "deadbeefcafebabe...",
"slsa_level": 3,
"timestamp": 1700000000
}Status Codes
| Code | Description |
|---|---|
200 OK | Attestation found and returned |
400 Bad Request | Invalid ID format |
401 Unauthorized | Missing or invalid API key |
404 Not Found | No attestation found with the given ID |
429 Too Many Requests | Read rate limit exceeded |
Example
curl http://localhost:8080/api/v1/attestations/abcdef0123456789 \
-H "Authorization: Bearer your-api-key"Error Format
All error responses use a consistent JSON format:
{
"error": "human-readable error message"
}All responses are application/json with UTF-8 encoding. The attestation submission endpoint enforces a maximum request body size of 10 MB.