For the complete documentation index, see llms.txt. This page is also available as Markdown.

Who Signs Your Credentials?

Every credential is signed by a key. Decide whether you hold it or LearnCard holds one for you.

Every credential is signed by a private key. You have two choices: you sign with your own seed, or LearnCard signs for you with a key it hosts on your behalf — a signing authority. Pick one; you can change later.

~5 min · After the Quickstart.

The one-line version

npx @learncard/cli setup-signing

Creates a hosted signing authority, registers it, and makes it your primary — the "LearnCard signs for you" path below, done. Idempotent: run it again and it tells you it's already set. Then npx @learncard/cli send --template sends from a template with no signing details in the call.

Pick a path

You sign

LearnCard signs for you

Your own signing service

Choose when

You run a server and are happy to keep a seed in an environment variable

You don't want to hold keys, or you use API tokens, templates, or the Developer Portal

You already run a VC-API issuer and it must be the signer of record

What you set up

Nothing — initLearnCard({ seed })

A hosted signing authority, once (below)

Register your endpoint (below)

What send() takes

signedCredential

templateUri or template

templateUri or template

Where the key lives

Your server

LearnCard, tied to your profile

Your service

Also unlocks

—

Claim links, Developer Portal templates, Partner Connect apps

Same as hosted

If you saw You must register a signing authority before using send without a pre-signed credential, you are on the LearnCard signs for you path without having done the one-time setup. Either finish it below, or switch to signing yourself and pass signedCredential.

You sign

Nothing to set up. The Quickstart does this: initLearnCard({ seed, network: true }) → issueCredential(...) → send({ signedCredential }). Keep the seed in an environment variable and back it up.

LearnCard signs for you

Do this once per profile per network (staging and production are separate). Afterwards send({ templateUri }) and send({ template }) work with no signing details.

  1. Open Guides → Issue Credentials → Signing Authority and click Create.

The first authority you create becomes your primary. Done.

Creating a hosted authority needs the LearnCard App API plugin in addition to the network plugin:

send() always uses your primary authority. To switch, call setPrimaryRegisteredSigningAuthority with another registered one.

Your own signing service

If you run a VC-API compliant issuer and it must be the signer, register it instead of a hosted authority. It needs a public HTTPS /issue endpoint and a DID.

Or in code:

send() will now call your endpoint to sign. If you register several authorities and need to choose per issuance, use the lower-level Universal Inbox API and pass configuration.signingAuthority: { name, endpoint }.

What you should see

After setup, send() with a template returns normally — no signing details in the call:

In the Developer Portal, Signing Authority shows the authority name with a Primary badge.

Troubleshooting

If…
Then

You must register a signing authority before using send without a pre-signed credential

You're sending a template without a primary authority. Finish LearnCard signs for you, or pass signedCredential.

learnCard.invoke.createSigningAuthority is not a function

You used initLearnCard. Hosted authorities need initLCALearnCard from @learncard/lca-api-plugin.

Profile not found

Create a profile first (createServiceProfile) — the Quickstart's setup.mjs does this.

It works on staging but not production

Authorities are per network. Register again on production — see Go to Production.

Next steps

The CLI's send --template saves the reusable script below after setting up your signer and template:

Last updated

Was this helpful?