Acuris eudi
Skill Acuris-GmbH/acuris-agent-context/agent-skill/acuris-eudi
Acuris Address Validation & Geocoding agent context — Claude Code plugin, Cursor rules/docs, and open Agent Skill (agentskills.io) packaged from one source of truth.
npx -y skills add Acuris-GmbH/acuris-agent-context --skill acuris-eudiAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Acuris EUDI Wallet Verifier — a hosted OID4VP relying-party service at https://eudi.acuris-geo.com that accepts EU Digital Identity Wallet presentations (SD-JWT VC PID), validates the credential against EU 27 member-state trust lists (LOTL → TSL → x5c → CRL), and cross-checks the disclosed residence address against Acuris's address-validation pipeline. Use when the user is integrating EUDI Wallet verification into a bank KYC / branch onboarding flow, building a relying-party backend that initiates verification sessions and polls for results, generating OID4VP presentation_definitions, handling SD-JWT VC responses, or interpreting verification_status, accuracy_type, and credential_validity in poll responses.
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
12.4 KB, ~2.9k tokens by cl100k_base, as published. Nobody here has run it
Overview
The Acuris EUDI Verifier is a hosted OID4VP (OpenID for Verifiable
Presentations) relying-party service at
https://eudi.acuris-geo.com. It accepts EU Digital Identity Wallet
presentations of the PID (Personal Identification Data) credential
(SD-JWT VC format), validates the credential against the EU 27
member-state Trusted Lists (LOTL → national TSL → x5c chain → CRL),
and cross-checks the disclosed residence address against Acuris's
address-validation pipeline.
This skill teaches AI assistants how to integrate the verifier as a relying party (RP) — typically a bank, fintech, or branch-onboarding backend that needs to verify a customer's residence address via their EUDI Wallet rather than via document upload.
You — the integrator — do not implement the wallet side. Your backend initiates a verification session, displays a QR code (or deep link) to the user, and polls for the verification result. The wallet posts the presentation directly to the Acuris verifier. The Acuris verifier validates trust + address and returns a structured result to your backend.
When to use this skill
Use this skill when the user is:
- Wiring an EUDI Wallet verification step into a bank KYC, branch onboarding, account-opening, or address-change flow.
- Building a relying-party backend that calls
POST /v1/eudi/sessionsto start a verification andGET /v1/eudi/sessions/<id>/resultto poll for the answer. - Generating an OID4VP
presentation_definitionfor the address-only field set Acuris supports. - Interpreting
verification_status,credential_validity,accuracy_type, andskipped_reasonin poll responses. - Wiring the QR-code / deep-link presentation to the user (typically inside a branch tablet, a teller app, or a mobile onboarding flow).
- Asking about EU 27 trust validation, qualified electronic signatures, or which member-state TSLs are currently loaded.
Do NOT use this skill for:
- Issuing PID credentials. Issuance is a member-state operation (in Germany, by Bundesdruckerei) — Acuris is verifier-side only.
- General-purpose KYC checks beyond address (sanctions screening, PEP check, source-of-funds verification). Acuris EUDI does not cover identity attribute validation beyond passing identity claims through; layer a dedicated KYC vendor for those.
- Pure address validation without EUDI Wallet (use the
acuris-addressskill instead — the underlying AV pipeline is the same, but you don't need OID4VP if the user is just typing). - Non-EU identity wallets (mDL / ISO 18013-5, U.S. state mobile DLs, W3C DIDs without OID4VP). Out of scope.
Integration shape at a glance
You implement two HTTP calls. The wallet handles everything in between.
┌──────────────┐
│ Your backend │
└──────┬───────┘
│ 1. POST /v1/eudi/sessions
│ → returns session_id + presentation_uri + qr_code_data_url
▼
┌──────────────┐
│ Your UI │ shows QR / deep link to user
└──────┬───────┘
│ user scans → wallet opens → consents to disclosure
▼
┌──────────────┐
│ EUDI Wallet │ fetches presentation_definition, builds VP
│ (user device)│ POSTs vp_token → /v1/eudi/callback
└──────┬───────┘
│
▼ (Acuris verifier validates trust + address)
┌──────────────┐
│ Your backend │ 2. GET /v1/eudi/sessions/<id>/result
│ │ → poll until verification_status != "pending"
└──────────────┘
You poll the result endpoint; the wallet → verifier handshake is opaque to you. Typical end-to-end time: 5-30 seconds depending on how long the user takes to consent.
API endpoints you actually call
| Endpoint | Method | Who calls it |
|---|---|---|
POST /v1/eudi/sessions | POST | Your backend — start a session |
GET /v1/eudi/sessions/{session_id}/result | GET | Your backend — poll for result |
GET /v1/eudi/healthz | GET | Your monitoring |
GET /v1/eudi/.well-known/openid-credential-verifier | GET | Wallets — verifier metadata |
POST /v1/eudi/callback | POST | The wallet — do not call this yourself |
GET /v1/eudi/presentation-definition/{id} | GET | The wallet — do not call this yourself |
The last two are documented for completeness; relying parties do not implement against them. They're the wallet's view of the verifier.
Detailed shapes for every endpoint are in
references/api-reference.md.
Quick start
# 1. Start a session
SID=$(curl -s -X POST https://eudi.acuris-geo.com/v1/eudi/sessions \
-H 'Content-Type: application/json' \
-d '{
"customer_id": "kyc-2026-12345",
"requested_fields": [
"resident_country", "resident_city", "resident_postal_code",
"resident_street", "resident_house_number"
]
}' | jq -r .session_id)
# 2. Render the returned qr_code_data_url or presentation_uri in your UI.
# User scans → wallet opens → consents.
# 3. Poll
while true; do
RESULT=$(curl -s https://eudi.acuris-geo.com/v1/eudi/sessions/$SID/result)
STATUS=$(echo "$RESULT" | jq -r .verification_status)
[ "$STATUS" != "pending" ] && break
sleep 2
done
echo "$RESULT" | jq .
verification_status ends in one of: valid, invalid, expired.
Each carries different metadata; full handling in
references/result-handling.md.
Defaults
- Production base URL:
https://eudi.acuris-geo.com. There is no separate sandbox host; pilots use acustomer_idprefix Acuris hands out (e.g.pilot-acme-…). - Address-only disclosure. The Acuris verifier whitelist accepts
three identity claims (
given_name,family_name,birth_date) alongside sixresident_*address sub-fields, but only theresident_*fields are cross-checked against Acuris reference data. Requesting non-whitelisted fields silently drops them (and logs the drop in your audit trail). Seereferences/field-disclosure.md. - Polling, not webhooks. Phase 2 ships polling-only. The
callback_urlfield onPOST /v1/eudi/sessionsis reserved for Phase 3 webhook delivery and is currently ignored. Build your integration to poll thepolling_urlreturned in the session response. - Session TTL: 10 minutes. A session that hasn't received a
callback within 10 minutes flips to
expired. Per-session TTL is configurable in Phase 3. - Don't echo the
nonce. The session response deliberately omits the OID4VP nonce as a top-level field; banks have no need for it and exposing it widens the replay-attack surface. It's embedded insidepresentation_uriif you need it for debugging. - mTLS for bank pilots. Phase 2 supports per-pilot mTLS on the
bank-facing endpoints. Default is unauthenticated; mTLS provisioning
is per-pilot. See
references/mtls-bank-pilot.md.
Common mistakes
-
Calling
/v1/eudi/callbackfrom your backend. That endpoint is for the user's wallet only. Your backend uses session-start + result-poll; the wallet handles thedirect_postbetween them. -
Polling too aggressively. A 2-second poll interval is fine. A 100ms interval will rate-limit you and won't return results faster — the bottleneck is the user's consent flow, which takes seconds.
-
Treating
verification_status: "pending"as an error. It means "the wallet hasn't called us back yet." Keep polling untilvalid,invalid, orexpired. -
Requesting identity claims you don't need. Selective disclosure is the whole point of EUDI Wallet. Requesting only the address sub-fields builds user trust and matches what the verifier actually validates. Asking for
given_nameorfamily_namealong with the address is permitted but the verifier only address-cross-checks, not identity-cross-checks. -
Ignoring
skipped_reason. When AV cross-reference doesn't run (e.g. partial disclosure, AV transport error), the poll response includes askipped_reasonstring. Treat that as a first-class outcome to log and surface to the bank operator — it isn't an error per se. -
Confusing
accuracy_typesemantics with the AV-only ones. In EUDI responses,accuracy_typeis one ofVerified,Corrected,Partial,Unverified— a four-bucket projection of the underlying Acuris cascade tuned for KYC compliance reasoning. Seereferences/result-handling.md. -
Not handling
country_codeoutside EUDI Wallet scope. EUDI Wallet is currently EU 27 + EEA non-EU. A disclosedresident_countryoutside this scope returnsaccuracy_type: "Unverified"with askipped_reasonofcountry code not supported by EUDI Wallet scope (alpha-2: XX). Surface this to the user — it isn't a bug in your code or theirs.
Implementation patterns
Detailed recipes live in the references. Load whichever matches the task:
- Backend relying-party integration (Node, Python, Go)
- Full session lifecycle: states, polling cadence, expiry, error recovery
- What the wallet does (read-only for context, not for implementation)
- Field disclosure and the address whitelist
- Result handling: accuracy_type, credential_validity, skipped_reason
- Trust model: LOTL, member-state TSLs, OJ anchors, CRL checks
- mTLS bank pilots
Trust model in one paragraph
The verifier walks every presented SD-JWT VC's x5c chain up to a root,
then verifies that root against the issuing member state's national
TSL (Trusted List), then verifies the TSL's signature against the EU
LOTL (List of Trusted Lists), then verifies the LOTL's signature
against the pinned OJ (Official Journal) trust anchors. Six OJ
anchors are pinned for rotation resilience. The leaf issuer
certificate's CRL is checked too. If any link breaks, the response
status is invalid and credential_validity.signature_valid or
.issuer_trusted will be false. Full mechanics in
references/trust-model.md.
Additional resources
- Live verifier metadata: https://eudi.acuris-geo.com/v1/eudi/.well-known/openid-credential-verifier
- Health check: https://eudi.acuris-geo.com/v1/eudi/healthz
- OID4VP spec: https://openid.net/specs/openid-4-verifiable-presentations-1_0.html
- SD-JWT VC spec: https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/
- EU LOTL: https://ec.europa.eu/tools/lotl/eu-lotl.xml
- Acuris pricing & EUDI pilot enquiries: https://acuris-geo.com/
What ships with it: 8 files
58.7 KB alongside SKILL.md
references/
- api-reference.md11.8 KB
- field-disclosure.md5.6 KB
- mtls-bank-pilot.md4.8 KB
- relying-party-integration.md8.7 KB
- result-handling.md6.8 KB
- session-lifecycle.md5.5 KB
- trust-model.md7.9 KB
- wallet-presentation-flow.md7.5 KB