From acuris
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.
How this skill is triggered — by the user, by Claude, or both
Slash command
/acuris:acuris-eudiWhen to use
Triggers: "EUDI Wallet", "EU Digital Identity Wallet", "OID4VP", "OpenID for Verifiable Presentations", "SD-JWT VC", "presentation_definition", "PID address verification", "relying party", "bank KYC EUDI", "eudi.acuris-geo.com", "/v1/eudi/sessions", "verification_status", "Acuris EUDI Verifier".
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
The Acuris EUDI Verifier is a hosted OID4VP (OpenID for Verifiable
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.
Use this skill when the user is:
POST /v1/eudi/sessions
to start a verification and GET /v1/eudi/sessions/<id>/result to
poll for the answer.presentation_definition for the address-only
field set Acuris supports.verification_status, credential_validity,
accuracy_type, and skipped_reason in poll responses.Do NOT use this skill for:
acuris-address skill instead — the underlying AV pipeline is the
same, but you don't need OID4VP if the user is just typing).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.
| 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.
# 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.
https://eudi.acuris-geo.com. There is no
separate sandbox host; pilots use a customer_id prefix Acuris hands
out (e.g. pilot-acme-…).given_name, family_name, birth_date)
alongside six resident_* address sub-fields, but only the
resident_* fields are cross-checked against Acuris reference
data. Requesting non-whitelisted fields silently drops them (and
logs the drop in your audit trail). See
references/field-disclosure.md.callback_url field on POST /v1/eudi/sessions is reserved for
Phase 3 webhook delivery and is currently ignored. Build your
integration to poll the polling_url returned in the session
response.expired. Per-session TTL is
configurable in Phase 3.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 inside
presentation_uri if you need it for debugging.references/mtls-bank-pilot.md.Calling /v1/eudi/callback from your backend. That endpoint
is for the user's wallet only. Your backend uses session-start +
result-poll; the wallet handles the direct_post between 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 until
valid, invalid, or expired.
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_name or
family_name along 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 a skipped_reason string. Treat that as a
first-class outcome to log and surface to the bank operator — it
isn't an error per se.
Confusing accuracy_type semantics with the AV-only ones.
In EUDI responses, accuracy_type is one of Verified, Corrected,
Partial, Unverified — a four-bucket projection of the
underlying Acuris cascade tuned for KYC compliance reasoning. See
references/result-handling.md.
Not handling country_code outside EUDI Wallet scope. EUDI
Wallet is currently EU 27 + EEA non-EU. A disclosed resident_country
outside this scope returns accuracy_type: "Unverified" with a
skipped_reason of country 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.
Detailed recipes live in the references. Load whichever matches the task:
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.
npx claudepluginhub acuris-gmbh/acuris-agent-context --plugin acurisProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.