Signing Worker Protocol
POST /v1/sign
Use the signer's approval and return one signature per digest, as a raw value or a complete CMS, plus the supported algorithms
Private beta. Qualified signatures are available on request. Request access and we enable them for your account. SWP/1 is in beta and may change.
The last call of a signing session. Use the authorization from authorize and return one signature per digest, in the same order. Your provider’s “sign hash” call is usually what this maps to.
Request
The common request fields, plus:
{
"credential_id": "cred_7Qk...",
"authorization": { "reference": "sad_3Fh..." },
"digests": [
{
"value": "n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=",
"hash_algorithm_oid": "2.16.840.1.101.3.4.2.1"
}
],
"sign_algo_oid": "1.2.840.10045.4.3.2"
}
| Field | Description |
|---|---|
credential_id | The same value authorize received. |
authorization.reference | The reference your authorize returned. |
digests | The same digests as in authorize, without label. |
sign_algo_oid | The algorithm SignatureAPI picked from your key_algo_oids. Always sent for raw. For cms, sent only when the credential returned both certificates and key_algo_oids. Otherwise your provider names its algorithm inside the CMS. |
signature_format | cms in a cms session. Absent in a raw session. |
Ignore fields you don’t know. Later versions of SWP/1 may add some.
What the digest is a hash of depends on the format. See What you sign.
Response
signatures holds one base64 value per digest, in the order of digests. A different count fails the session with worker response invalid: signatures count.
raw
{ "status": "completed", "signatures": ["MEUCIQD..."] }
Each value is a bare signature, as described in Signing input and output. Don’t include certificates: in a raw session it fails the session with worker response invalid: sign.certificates. SignatureAPI already has the chain from credential.
cms
{
"status": "completed",
"signatures": ["MIIGxwYJKoZIhvcNAQcCoIIGuDCCBrQCAQEx..."],
"certificates": [
"-----BEGIN CERTIFICATE-----\n...signer...\n-----END CERTIFICATE-----",
"-----BEGIN CERTIFICATE-----\n...intermediate...\n-----END CERTIFICATE-----"
]
}
| Field | Required | Description |
|---|---|---|
signatures | Yes | One complete detached CMS signature per digest, base64. DER is preferred, BER is accepted. See Requirements on a CMS signature. |
certificates | Yes | The chain in PEM, signer certificate first. The CMS must be signed by the first certificate. Without it, the session fails with worker response invalid: sign.certificates. |
If credential returned a signer certificate, the first certificate here must be the same one. Otherwise the session fails with signer-certificate-mismatch.
sign never answers pending. It must also be idempotent: a repeated request with the same Idempotency-Key returns the stored signatures and never signs again. SignatureAPI doesn’t retry sign on a retryable failure.
Signing input and output
This section applies to raw. For cms, your provider signs and encodes the signature inside the CMS.
| Key type | What you sign | What you return |
|---|---|---|
| RSA | The DER DigestInfo of the digest, with PKCS#1 v1.5 padding. Don’t hash again. | The raw PKCS#1 signature, base64. |
| ECDSA (P-256, P-384, P-521) | The raw digest bytes. Don’t hash again. | A DER-encoded ECDSA-Sig-Value (RFC 3279), base64. Not the compact r‖s form. |
Your bytes go verbatim into the PDF, and PDF readers expect DER. SignatureAPI rejects an ECDSA signature in any other encoding. If your provider returns r‖s, convert it.
If your provider returns a complete CMS or PKCS#7 signature instead of a bare value, use the cms format.
Supported algorithms
List these OIDs in key_algo_oids, or in Key algorithm OIDs for a static certificate:
| OID | Algorithm |
|---|---|
1.2.840.10045.4.3.1 | ecdsa-with-SHA224 |
1.2.840.10045.4.3.2 | ecdsa-with-SHA256 |
1.2.840.10045.4.3.3 | ecdsa-with-SHA384 |
1.2.840.10045.4.3.4 | ecdsa-with-SHA512 |
1.2.840.113549.1.1.11 | sha256WithRSAEncryption |
1.2.840.113549.1.1.12 | sha384WithRSAEncryption |
1.2.840.113549.1.1.13 | sha512WithRSAEncryption |
1.2.840.113549.1.1.1 | rsaEncryption (key type only) |
1.2.840.10045.2.1 | id-ecPublicKey (key type only) |
SignatureAPI picks the first OID in your list that names a full signature algorithm, one of the first seven rows. If your list has none, it uses your first OID.
Every digest is SHA-256. If the picked algorithm names another hash (SHA-224, SHA-384 or SHA-512), the session fails with sign-algorithm-unsupported before authorize, so the signer is never asked to approve. List a SHA-256 algorithm before any other full algorithm. The key-type OIDs name no hash, so they always pass.