Skip to content

Credenco 🇳🇱

Credenco: Issuer and Verifier for the France Identité Playground

Credenco

🇳🇱 Credenco builds the Business Wallet: infrastructure that lets organisations issue, hold and verify credentials. We contribute both an Issuer and a Verifier to the EUDIW Unfold Playground, so you can test both directions in one session against a wallet you already carry.

First time here? If you carry France Identité, the age check under Demo scenarios works with it as it stands, in about a minute. Every other flow needs the Credenco Personal Wallet, because France Identité holds its own credentials rather than ours; Which wallet you need below tells you where to get it. The full tour is issue the three test credentials and then rent a car with them, about ten minutes end to end. Everything runs cross-device with a QR code or same-device with a wallet link, and needs no account. The whole demo is available in French: append ?lang=fr to any link on this page.

Playground base URL: https://api.playground.france-identite.gouv.fr/credenco/demo/ (also self-hosted at https://playground.credenco.com/)


At a glance

Field Value
Roles Issuer and Verifier. You bring your own wallet
Profiles DIIP v2/v3 and v4/v5, and HAIP
Protocols OpenID4VCI and OpenID4VP
Query language DCQL on DIIP v4/v5 and HAIP; Presentation Exchange on DIIP v2/v3
Formats SD-JWT VC (dc+sd-jwt / vc+sd-jwt), JWT VC, and ISO/IEC 18013-5 mdoc (mso_mdoc)
Client identification x509_san_dns on the age check; decentralized_identifier elsewhere. See Playground specifics
Response modes direct_post and direct_post.jwt, set per query. See Playground specifics
Revocation Supported: IETF Token Status List (StatusList2021 for older credentials; no Bitstring Status List). The demo credentials on this page are issued without one
Credential types Issued: Personal ID, driving licence, bank account, and a Wayfare reservation. Verified: those, plus the France Identité age-verification mdoc
Interaction modes Cross-device (QR code) and same-device (wallet link)
Languages English and French, plus Dutch, German, Finnish, Norwegian, Portuguese and Swedish. Append ?lang=fr to any link
Operator Credenco B.V., Netherlands
Status Sandbox, suitable for integration testing

Why Credenco

Both directions, one session. Plenty of entries here issue and verify. What the Wayfare scenario adds is the return leg: it verifies identity, age and licence category, takes payment by presenting a bank-account credential, and then issues the reservation back into the wallet, inside the same session, without sending you anywhere else to collect it.

One credential definition, every profile. DIIP is the Decentralized Identity Interoperability Profile, and together with HAIP it decides how a request is shaped: DCQL and dc+sd-jwt on DIIP v4/v5 and HAIP, Presentation Exchange and vc+sd-jwt on DIIP v2/v3. One credential definition can therefore be tested against wallets on different profiles without a redeploy.

From concept to production. Every flow below carries a maturity badge, so you can see what is production-grade and what is still on its way there. Pilot runs in a real pilot programme; Concept is built and demonstrable but not yet hardened against other implementations. We publish both, because what is possible today tells you more than a list of only the finished parts.


Conformance

These are the test results for the Credenco Business Wallet, the engine behind this playground, not the front end.

  • DIIP v5 conformance, reached through the FIDES Integrated Test Bed for both issuance and presentation. It is a first-class profile in the stack: it selects RFC 8414 metadata discovery, the credentials response shape and DCQL.
  • WE BUILD Interoperability Test Bed, all test cases passed, as one of the first wallet providers in the consortium to get there. We are a member of the Large-Scale Pilot for the European Business Wallet.
  • Trust resolution runs against ETSI trusted lists and a locally maintained issuer list. EBSI is supported for DID registration, which is a separate concern from resolving trust at verification time.

These are test bed results, not certification. As of August 2026 no certified EUDI Wallet Solution exists and we make no claim to be one.


Supported standards

Trust material and metadata. The credential offer carries the issuer URL, so a wallet resolves the rest on its own. These are the paths it will find, all unauthenticated:

What Path
Issuer metadata /public/{wallet}/{issuer}/.well-known/openid-credential-issuer
Issuer metadata, RFC 8414 form /.well-known/openid-credential-issuer/public/{wallet}/{issuer}
Authorization server metadata /public/{wallet}/{issuer}/.well-known/oauth-authorization-server
JWT VC issuer metadata /.well-known/jwt-vc-issuer/public/{wallet}/{issuer}
Issuer JWKS /public/{wallet}/{issuer}/jwks
Verifier JWKS /api/oidc/jwks/{wallet}

There is no .well-known/jar-issuer and no OpenID Federation endpoint. Our request objects carry the signing certificate in the x5c header instead.


Playground specifics

Versions. On DIIP v4/v5 and HAIP we speak the OpenID4VP 1.0 wire format: DCQL queries, a vp_token keyed by query id, a scheme-prefixed client_id, and a signed request object fetched by request_uri. One deviation is worth naming up front. Encrypted responses still advertise the pre-1.0 authorization_encrypted_response_alg and authorization_encrypted_response_enc parameters rather than the 1.0 encrypted_response_enc_values_supported. DIIP v2/v3 stay on the pre-1.0 Presentation Exchange profile.

On the issuance side the draft follows the profile: OpenID4VCI draft 11 on DIIP v2, draft 13 on v3, draft 15 on v4, and 1.0 on v5 and HAIP.

Not implemented on any profile: transaction_data, request_uri_method as a request parameter, and verifier_info. If your wallet is pinned to a particular draft, tell us before you test and we will say plainly whether it will work.

Fetching the request object. GET and POST on the request_uri both return the signed request object. The POST semantics of OpenID4VP are not implemented yet, though: wallet_metadata and wallet_nonce in the body are ignored and no wallet_nonce claim comes back. If your wallet uses POST to get nonce binding, it will not get it yet.

Response modes. Both are implemented. An encrypted response is a JWE with ECDH-ES on P-256 and A256GCM content encryption.

Which mode a request carries is decided per query rather than globally. The France Identité age check goes out as direct_post.jwt, because that wallet only answers encrypted requests; every other scenario on the page goes out as direct_post. If you need the encrypted mode on another scenario, contact us: it is a setting on the request, not a rebuild.

Client identification. The France Identité age check carries client_id: x509_san_dns:..., with its self-signed certificate travelling in the x5c header of the request object; the SAN matches the request host, so no whitelisting is needed. The other scenarios carry client_id: decentralized_identifier:did:web:... and will move to x509_san_dns with the certificate published under Certificate below, DNS SAN demopidprovider.acc.credenco.com.

Trust setup for visiting wallets. There are two separate trust anchors here, and they are not the same certificate.

To trust our presentation requests, no whitelisting is needed for the age check: its certificate travels in the x5c header of the request object. For the other scenarios, the reader certificate published under Certificate below applies once they move to x509_san_dns; it is self-signed and carries no chain.

To trust the credentials we issue, use the X.509 chain our issuer carries in the x5c header of each credential, which lets a wallet anchor trust in a chain rather than a DID. That chain is not reproduced here; it is available on request.


Demo scenarios

Carrying France Identité? Start with the age check below, one minute. The rest of the page is one funnel, not a menu: issue three credentials, then spend them at a rental service that actually asks for them. You can also run a presentation on its own.

Prove you are over 18 with France Identité. The one scenario on this page that needs no Credenco credentials: present the age-verification attestation from your France Identité wallet, and nothing else. The request goes out as direct_post.jwt, since France Identité only answers encrypted requests. Try it → Pilot

The France Identité app after the age check: data shared successfully

Issue three test credentials. A Personal ID (name, date of birth, nationality, address), a driving licence including the categories you may drive, and a bank account. All three are SD-JWT VC, issued over OpenID4VCI. The data is fictional. You receive the credentials of Klaas Jansma, so nothing about you is stored anywhere. Try it → Pilot

Wayfare car rental, end to end. A rental service we built to show what a booking looks like when the customer already carries verified credentials. No account, no form. You pick a car, prove four things about yourself, pay by presenting the bank-account credential instead of typing an IBAN, and the reservation is issued back into your wallet, which is then all you need at the desk. Try it → Pilot

Prove who you are and that you may drive. The OpenID4VP exchange on its own, without the rental around it: one request asking for the Personal ID and the driving licence together. The page lists exactly which attributes came back. Both are mandatory, so issue them first. Try it → Pilot

What the verifier learns, and what it does not. Because the credentials are SD-JWT VC, the holder answers with a subset rather than handing over a document. The Personal ID carries age_over_18 and age_over_21 next to birth_date, so a verifier that only needs to know whether someone is old enough can ask for the predicate and never see the date. The licence works the same way: category B without the full history. The answer stays signed by the issuer, so disclosing less costs nothing in assurance. After each presentation the page lists which attributes came back, so the holder sees it too and not only we do.

The rental, screen by screen

The whole funnel in eight screens, in the order you will see them yourself. The playground and Wayfare are shown in English; both also run in French (?lang=fr), and the wallet follows your phone's language.

Issue the test credentials. The page tracks which of the three you already hold; each card starts its own issuance.

Step two of the playground: issue your test credentials

Scan, or stay on your phone. Every credential offer comes as a QR code for cross-device and a wallet link for same-device, and the page notices by itself when the credential lands.

The QR panel, waiting for the wallet

Pick a car at Wayfare. No account, no form: the booking starts with the car, not with your data.

Picking the Volkswagen Transporter at Wayfare

One request, three credentials. Wayfare says up front what it will verify: your name, that you are over 21, licence category B, and your address.

Wayfare's identity step, a single OpenID4VP request

Verified, and nothing more. What came back is exactly the list from the request; the age arrives as over 21, not as a date of birth.

The verified identity of Klaas Jansma

Pay by presenting, not typing. The bank-account credential replaces the IBAN form field.

Authorising the payment with the bank-account credential

The reservation is a credential too. Wayfare issues the booking straight back into your wallet, with a booking code to match.

The rental booking credential, ready to add to the wallet

What ends up in the wallet. Four cards: the three test credentials and the rental confirmation, which is all the desk needs to see.

The wallet afterwards, holding all four credentials


Maturity

The badges are the ones defined under Why Credenco. Where a flow is not switched on for this playground, the note says what switches it on.

Flow Status Note
Issue Personal ID (SD-JWT VC) Pilot Works with wallets that match on our vct; see the caveat below
Issue driving licence (SD-JWT VC) Pilot Not an ISO mDL
Issue bank account (SD-JWT VC) Pilot Dutch-language claim names
Present Personal ID and driving licence Pilot One query, both credentials mandatory
Wayfare end to end (verify → pay → issue reservation back) Pilot A real, running service. Works with wallets that accept our issuer; see the caveat below
Verify an mdoc presentation Pilot The full ISO check: DeviceResponse status, a session transcript bound to client_id and nonce, the device signature, element-level tamper detection, and the issuer chain up to a configured IACA
Verify a France Identité presentation Pilot Verified live against the France Identité wallet in the Credenco Business Wallet, including the age-verification mdoc (eu.europa.ec.av.1), anchored on the France Identité IACA. Wired to the age check under Demo scenarios
Present an mdoc from our own wallet Concept The Credenco Personal Wallet answers with a full ISO DeviceResponse: DeviceSigned with an ES256 device signature over the OpenID4VP session transcript, and element-level selective disclosure. Verified against our own verifier, not yet against other implementations
Issue an mdoc Concept Signs an MSO with COSE_Sign1 and returns IssuerSigned, with the ISO 18013-5 Annex B document signer profile enforced. Not yet exercised against other wallets
W3C Digital Credentials API (dc_api) Not built Scheduled as soon as someone needs it

Two things to know before you write a matcher. Our credentials carry vct Pid and urn:eu:credential:mdl:1, which are Credenco-scoped rather than the canonical urn:eudi:pid:1 or eu.europa.ec.eudi.pid.1, so a verifier querying the canonical identifiers finds no match. And the boolean-looking claims in the Personal ID are issued as the JSON string "true", not as a boolean. Both are configuration rather than code. Tell us what you need and we will change them.

Which wallet you need. The Credenco Personal Wallet (iOS, Android), which holds personal and organisational credentials alike. France Identité cannot hold ours: its OID4VCI External Issuance runs the other way, with France Identité as the issuer delivering an age-verification mdoc into third-party wallets, and there is no documented path for an outside issuer to write into it. That is the standard working as intended. A national identity wallet should not let just anyone write into it.


Certificate

The verifier X.509 certificate below is the one the remaining scenarios will carry when they move to x509_san_dns. The age check needs no whitelisting: its certificate travels in the x5c header of the request object. Client identification under Playground specifics says where things stand today.

Subject:     C=NL, O=Credenco B.V., CN=demopidprovider.acc.credenco.com
Valid:       Aug 24 11:25:20 2026 GMT to Nov 26 11:25:20 2028 GMT
Key:         EC P-256
DNS SAN:     demopidprovider.acc.credenco.com

Full certificate (PEM):

-----BEGIN CERTIFICATE-----
MIICNDCCAdqgAwIBAgIUL7uvAR6b21Ve3ZO4gvs/StUxutYwCgYIKoZIzj0EAwIw
UDELMAkGA1UEBhMCTkwxFjAUBgNVBAoMDUNyZWRlbmNvIEIuVi4xKTAnBgNVBAMM
IGRlbW9waWRwcm92aWRlci5hY2MuY3JlZGVuY28uY29tMB4XDTI2MDgyNDExMjUy
MFoXDTI4MTEyNjExMjUyMFowUDELMAkGA1UEBhMCTkwxFjAUBgNVBAoMDUNyZWRl
bmNvIEIuVi4xKTAnBgNVBAMMIGRlbW9waWRwcm92aWRlci5hY2MuY3JlZGVuY28u
Y29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEvwPL97vOD24ooCHCgJ9bXSbG
m8pamnHaAvpkZ8zjwSu2xBEluO4TKD8Y2rIdlEIfADCL2t6m0V17k3jlai5dnaOB
kTCBjjAdBgNVHQ4EFgQUjVa/18HDC6/Wr/8AXATus0Mss8cwHwYDVR0jBBgwFoAU
jVa/18HDC6/Wr/8AXATus0Mss8cwDwYDVR0TAQH/BAUwAwEB/zArBgNVHREEJDAi
giBkZW1vcGlkcHJvdmlkZXIuYWNjLmNyZWRlbmNvLmNvbTAOBgNVHQ8BAf8EBAMC
B4AwCgYIKoZIzj0EAwIDSAAwRQIhAJXdkE7gwUB0goFKbljYq0iIaMM3HnTSOLWU
+WDfPzNyAiAcM11GKhv1dVDqUfrHJO6woEdzlZdwpUMAlnxTAWU4Mg==
-----END CERTIFICATE-----

Troubleshooting

  • "No credentials available" almost always means one of the required credentials is missing from your wallet. The presentation query asks for the Personal ID and the driving licence together and both are mandatory, so issue the one you skipped and try again. The page names the missing credential.
  • "One or more credentials could not be verified" usually means your wallet will not accept credentials from an issuer it does not already know. Use the Credenco Personal Wallet; see Which wallet you need above.
  • Start a new reservation rather than reloading a page you had already scanned on. Wayfare evaluates everything presented within one booking session, so an earlier attempt can keep a stale result on screen.

Get in touch

Happy to help with testing, integration questions, or a credential type that is not on this list. We read everything that comes in and we answer.

If something goes wrong, the fastest way to get it fixed is to tell us which flow you were in, which wallet app and version you used, your device and OS, and the session identifier shown on the page. With those five things we can usually reproduce it the same day.


With thanks to the France Identité team and the EUDIW Unfold initiative.