A previous release had provenance metadata, but this release does not. View details.
didis-py
Official Python SDK for the DID.is public API: DID resolution with evidence, W3C DID Resolution, verifiable credentials, explicit policies, and MCP/A2A agent trust. Sync and async clients on httpx; Python 3.11+. Responses are plain dicts typed with TypedDict (didis.types), so editors and mypy know their shape.
The distribution is didis-py; the import name is didis.
Install
pip install didis-py
Usage
from didis import DidisClient, AsyncDidisClient, DidisError
# Defaults to the public API at https://did.is/api; pass base_url when self-hosting.
with DidisClient() as didis:
r = didis.resolve("did:web:identity.foundation")
print(r["verdict"]["headline"])
for d in r["dimensions"]:
print(d["label"], d["state"])
# DID Resolution v1 (W3C CR Draft HTTPS binding, unmodified)
w3c = didis.resolve_w3c("did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK")
# Live resolution stream (server-sent events)
for event, data in didis.stream("did:web:identity.foundation"):
if event == "stage":
print(data["label"], data["status"])
# Credentials: VC DM 2.0 / 1.1, Data Integrity (eddsa-jcs-2022, ecdsa-jcs-2019), VC-JOSE/VC-JWT
credential = {
"@context": ["https://www.w3.org/ns/credentials/v2"],
"type": ["VerifiableCredential"],
"issuer": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"validFrom": "2026-01-01T00:00:00Z",
"credentialSubject": {"id": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLdmQR63zLFKfvUwi3"},
}
vc = didis.verify_credential(credential)
print(vc["status"], vc["headline"])
# Policies are explicit rules, never scores
out = didis.evaluate_policy(
"did:web:example.com",
{"rules": {"allowedMethods": ["web", "webvh"], "domainBinding": "required"}},
)
print(out["evaluation"]["status"])
# Agents
mcp = didis.inspect_mcp("https://mcp.example.com/mcp")
print(mcp["status"], mcp["inventoryHash"], len(mcp["tools"]))
chain: list[str] = [] # delegation receipt JWS strings, root first
decision = didis.authorize(chain, "payments.refund", trusted_roots=["did:web:example.com"])
print(decision["authorization"]["decision"])
try:
didis.resolve("did:web:does-not-exist.invalid")
except DidisError as e:
print(e.status, e.problem.get("code"), e.problem.get("detail"))
async def main() -> None:
async with AsyncDidisClient() as didis:
diff = await didis.diff("did:web:example.com")
print(diff)
Identifiers are percent-encoded exactly once (quote(did, safe="")). Non-2xx responses raise DidisError with the RFC 9457 problem body.
Guard agent tools
A guarded tool function runs only when (1) the tool definition the agent received still matches the one you approved and (2) DID.is says the agent's registered delegation grants the tool. Every failure raises DidisGuardError and the function does not run (fail-closed).
import os
from didis import DidisClient, DidisGuard, pin_tool_definitions
didis = DidisClient()
# Once, after reviewing the server's tools/list: store these pins in your config.
pins = pin_tool_definitions(reviewed_tools)
guard = DidisGuard(
didis,
agent=os.environ["AGENT_DID"], # from configuration, never from model output
root=os.environ["ROOT_DID"], # require this delegation root
pins=pins,
require_pins=True,
)
@guard.tool(
"github_create_issue", # the name in tools/list (pin key)
definition=lambda: current_tools["github_create_issue"],
capability="github:create_issue", # what the delegation must grant
)
def create_issue(title: str, body: str) -> dict:
return github.create_issue(title, body)
Tool name vs capability. MCP and OpenAI tool names may only contain letters, digits, _, - and ., so a tool cannot be called github:create_issue. DID.is capabilities use : namespaces so that github:* can grant a whole group. Pass both: the tool name is used for the pin and error messages, capability is what DID.is is asked about. Without capability, the tool name is used. A capability must be exact (no *, no empty segments, no spaces); an invalid one raises GUARD_MISCONFIGURED before any network call. Since 0.2.1.
Guarding MCP clients (mcp 2.x), LangChain and the OpenAI Agents SDK: see examples/ and Guard agent tools.
- The definition check is local (RFC 8785 JCS + SHA-256, the same
definitionSha256DID.is reports) and makes no network call. - The delegation check calls
verify_tool. An ALLOW is reused for 30 s by default (allow_cache_seconds), never past the delegation expiry; DENY and errors are never cached. - Error codes:
TOOL_DRIFT,TOOL_DEFINITION_MISSING,TOOL_NOT_AUTHORIZED,GUARD_UNAVAILABLE,GUARD_MISCONFIGURED. - One tool only:
@didis_guard(client, agent, "github_create_issue", root, capability="github:create_issue", pin=..., definition=...). WithAsyncDidisClientuseAsyncDidisGuard(ordidis_guard, which picks it automatically) onasync deffunctions. on_decisionandDidisGuardError.detailinclude bothtoolandcapability.attest_mcp_pins(client, endpoint, pins)asks DID.is to inspect a public MCP server and compares its hashes with your pins. Run it at startup or deploy time, not per call: it is an outbound, rate-limited request, and servers that need login or run on a private network cannot be inspected.
Webhooks
Console project monitor events use verify_customer_monitor_signature:
from didis import verify_customer_monitor_signature
ok = verify_customer_monitor_signature(
secret,
raw_body,
request.headers["X-DIDIS-Signature"],
tenant_id=tenant_id,
project_id=project_id,
event_id=request.headers["X-DIDIS-Event-ID"],
)
For self-hosted admin daemon monitoring deliveries, use verify_webhook_signature:
from didis import verify_webhook_signature
ok = verify_webhook_signature(
secret,
request.headers["x-didis-timestamp"],
raw_body,
request.headers["x-didis-signature-256"],
)
Public API reference: https://did.is/developers. Monitoring routes need admin_token= and are only available on self-hosted deployments; they are not exposed by the public API.
License
MIT
Metadata
Release files for didis-py 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Loss of provenance
These files do not have provenance metadata, despite files in a prior release including this data.
We recommend further investigation before installing these files. View details.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| didis_py-0.2.1.tar.gz | 30.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| didis_py-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 48.1 kB
Release files / didis_py-0.2.1.tar.gz
Loss of provenance
This file belongs to a release without provenance metadata, despite a prior release including this data.
We recommend further investigation before installing this file. View details.
| Download URL | didis_py-0.2.1.tar.gz |
|---|---|
| Size | 30.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1ea3f17204d96548888683243118c682c31f66aeae006c0ee29df3ea02f467de
|
|
BLAKE2b-256 checksum How to use checksums |
35b13bf101dd0a599afdd684ef1689882610bda0e5d4cb2cc88969294db902e9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / didis_py-0.2.1-py3-none-any.whl
Loss of provenance
This file belongs to a release without provenance metadata, despite a prior release including this data.
We recommend further investigation before installing this file. View details.
| Download URL | didis_py-0.2.1-py3-none-any.whl |
|---|---|
| Size | 18.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cb5ae79d837821e6a0faa1f5cd10f6cd9c11985b329427dc3ff3cf05b4196cdb
|
|
BLAKE2b-256 checksum How to use checksums |
98b1a4064ea898f49bc43e18a16b63c9f7114b1d3612b61304c4567247c0164c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Security for didis-py 0.2.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Loss of provenance
A previous release of these files had provenance metadata, but this release does not.
While this could reflect a routine change by the project maintainers, it may also indicate that the release files have been compromised.
Release comparison
- Removed 0.2.0 2 files With provenance
- Added 0.2.1 2 files Without provenance
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.