Recertification
The Recertification resource (client.recertification) manages recertification cycles and audit reviews programmatically.
Methods
create_cycle(space_slug, *, name, due_date, cycle_type=, description=)
Create a new recertification cycle.
| Parameter | Type | Default | Description |
|---|---|---|---|
space_slug | str | required | Space identifier |
name | str | required | Cycle name |
due_date | str | required | ISO-8601 due date |
cycle_type | str | "product" | "product" or "access" |
description | str | None | None | Optional description |
Returns: RecertificationCycle
cycle = await client.recertification.create_cycle(
"marketing-analytics",
name="Q1 2026 PII Review",
due_date="2026-03-31T23:59:59Z",
cycle_type="product",
description="Quarterly review of PII-tagged products.",
)
print(f"Created cycle: {cycle.id}")
list_cycles(space_slug)
List all recertification cycles in a space.
| Parameter | Type | Description |
|---|---|---|
space_slug | str | Space identifier |
Returns: list[RecertificationCycle]
cycles = await client.recertification.list_cycles("marketing-analytics")
for c in cycles:
print(f"{c.name}: {c.status} ({c.reviewed_count}/{c.audit_count})")
get_cycle(space_slug, cycle_id)
Get a cycle with all its audit items.
| Parameter | Type | Description |
|---|---|---|
space_slug | str | Space identifier |
cycle_id | UUID | Cycle UUID |
Returns: RecertificationCycle (with embedded audits list)
cycle = await client.recertification.get_cycle(
"marketing-analytics", cycle_id
)
for audit in cycle.audits:
print(f"{audit.resource_name}: {audit.status}")
update_config(space_slug, cycle_id, *, filters=, request_title_template=, request_description_template=)
Update the cycle's filters and request templates. All parameters are optional — only provided fields are updated.
| Parameter | Type | Default | Description |
|---|---|---|---|
space_slug | str | required | Space identifier |
cycle_id | UUID | required | Cycle UUID |
filters | dict | None | None | Filter object (keys: tags, product_type, criticality) |
request_title_template | str | None | None | Jinja2 title template |
request_description_template | str | None | None | Jinja2 description template |
Returns: RecertificationCycle
cycle = await client.recertification.update_config(
"marketing-analytics",
cycle_id,
filters={"tags": ["pii"], "criticality": ["High"]},
request_title_template="Recertify {{ product_name }}",
)
delete_cycle(space_slug, cycle_id)
Permanently delete a cycle and all its audit items.
| Parameter | Type | Description |
|---|---|---|
space_slug | str | Space identifier |
cycle_id | UUID | Cycle UUID |
Returns: None
await client.recertification.delete_cycle("marketing-analytics", cycle_id)
populate_cycle(space_slug, cycle_id)
Auto-populate audit items from live data. Idempotent — existing items are skipped.
| Parameter | Type | Description |
|---|---|---|
space_slug | str | Space identifier |
cycle_id | UUID | Cycle UUID |
Returns: PopulateResult
result = await client.recertification.populate_cycle(
"marketing-analytics", cycle_id
)
print(f"Created {result.created} audit items")
recertify_all(space_slug, cycle_id)
Create recertification requests for all pending audit items in bulk.
| Parameter | Type | Description |
|---|---|---|
space_slug | str | Space identifier |
cycle_id | UUID | Cycle UUID |
Returns: RecertifyAllResult
result = await client.recertification.recertify_all(
"marketing-analytics", cycle_id
)
print(f"Created {result.created} requests")
archive_cycle(space_slug, cycle_id)
Archive a cycle, hiding it from the default list view.
| Parameter | Type | Description |
|---|---|---|
space_slug | str | Space identifier |
cycle_id | UUID | Cycle UUID |
Returns: RecertificationCycle
await client.recertification.archive_cycle("marketing-analytics", cycle_id)
unarchive_cycle(space_slug, cycle_id)
Restore an archived cycle to the default list.
| Parameter | Type | Description |
|---|---|---|
space_slug | str | Space identifier |
cycle_id | UUID | Cycle UUID |
Returns: RecertificationCycle
await client.recertification.unarchive_cycle("marketing-analytics", cycle_id)
complete_cycle(space_slug, cycle_id)
Mark a cycle as completed (read-only).
| Parameter | Type | Description |
|---|---|---|
space_slug | str | Space identifier |
cycle_id | UUID | Cycle UUID |
Returns: RecertificationCycle
completed = await client.recertification.complete_cycle(
"marketing-analytics", cycle_id
)
print(f"Cycle status: {completed.status}")
cancel_cycle(space_slug, cycle_id)
Mark a cycle as cancelled. Can be reopened later.
| Parameter | Type | Description |
|---|---|---|
space_slug | str | Space identifier |
cycle_id | UUID | Cycle UUID |
Returns: RecertificationCycle
cancelled = await client.recertification.cancel_cycle(
"marketing-analytics", cycle_id
)
get_filter_suggestions(space_slug)
Get the available filter values for cycle population. Returns the distinct tags, product types, and criticalities present in the space — useful for building autocomplete UIs.
| Parameter | Type | Description |
|---|---|---|
space_slug | str | Space identifier |
Returns: FilterSuggestions
suggestions = await client.recertification.get_filter_suggestions(
"marketing-analytics"
)
print(f"Tags: {suggestions.tags}")
print(f"Types: {suggestions.product_types}")
print(f"Criticalities: {suggestions.criticalities}")
review_audit(audit_id, *, status, comments=)
Approve or reject an audit item.
| Parameter | Type | Default | Description |
|---|---|---|---|
audit_id | UUID | required | Audit UUID |
status | str | required | "approved" or "rejected" |
comments | str | None | None | Optional reviewer notes |
Returns: RecertificationAudit
audit = await client.recertification.review_audit(
audit_id,
status="approved",
comments="Access confirmed for ongoing reporting.",
)
print(f"Audit {audit.id}: {audit.status}")
create_audit_request(space_slug, audit_id)
Create a recertification request for a single audit item. The request is routed through the cycle's configured workflow.
| Parameter | Type | Description |
|---|---|---|
space_slug | str | Space identifier |
audit_id | UUID | Audit UUID |
Returns: RecertificationAudit (with request_id populated)
audit = await client.recertification.create_audit_request(
"marketing-analytics", audit_id
)
print(f"Request created: {audit.request_id}")
Models
RecertificationCycle
| Field | Type | Description |
|---|---|---|
id | UUID | Cycle identifier |
name | str | Cycle name |
description | str | None | Optional description |
cycle_type | str | "product" or "access" |
status | str | "open", "in_review", "completed", "cancelled" |
due_date | datetime | None | Review deadline |
start_date | datetime | None | When the cycle was created |
completed_at | datetime | None | When the cycle was completed |
space_id | UUID | None | Space the cycle belongs to |
created_by_id | UUID | None | User who created the cycle |
audit_count | int | Total audit items |
reviewed_count | int | Decided audit items |
audits | list[RecertificationAudit] | Embedded audits (when fetched via get_cycle) |
RecertificationAudit
| Field | Type | Description |
|---|---|---|
id | UUID | Audit identifier |
cycle_id | UUID | Parent cycle |
resource_id | UUID | Resource being reviewed |
resource_name | str | None | Resource display name |
resource_type | str | None | Resource type (e.g., Table, Dashboard, SourceSystemRole) |
status | str | "pending", "approved", "rejected", "expired" |
reviewer_id | UUID | None | Who made the decision |
reviewed_at | datetime | None | When the decision was made |
comments | str | None | Reviewer comments |
product_id | str | None | Associated data product ID (product cycles) |
source_system_id | str | None | Associated source system ID (access cycles) |
has_pending_request | bool | Whether a recertification request is in-flight |
request_id | str | None | ID of the linked recertification request |
PopulateResult
| Field | Type | Description |
|---|---|---|
created | int | Number of audit items created |
RecertifyAllResult
| Field | Type | Description |
|---|---|---|
created | int | Number of recertification requests created |
FilterSuggestions
| Field | Type | Description |
|---|---|---|
tags | list[str] | Distinct tag values in the space |
product_types | list[str] | Distinct product type values |
criticalities | list[str] | Distinct criticality values |
Example: Full Cycle Automation
from qarion import QarionClient
async def run_quarterly_review():
async with QarionClient(api_key="your-api-key") as client:
# 1. Create a cycle with filters
cycle = await client.recertification.create_cycle(
"marketing-analytics",
name="Q1 2026 Review",
due_date="2026-03-31T23:59:59Z",
cycle_type="product",
)
# 2. Scope to PII products only
await client.recertification.update_config(
"marketing-analytics",
cycle.id,
filters={"tags": ["pii"]},
request_title_template="Recertify {{ product_name }}",
)
# 3. Populate audit items
result = await client.recertification.populate_cycle(
"marketing-analytics", cycle.id
)
print(f"Populated {result.created} items")
# 4. Create requests for all pending items
bulk = await client.recertification.recertify_all(
"marketing-analytics", cycle.id
)
print(f"Created {bulk.created} requests")
# 5. (Alternatively) Review each audit item directly
detail = await client.recertification.get_cycle(
"marketing-analytics", cycle.id
)
for audit in detail.audits:
if audit.status == "pending":
await client.recertification.review_audit(
audit.id,
status="approved",
comments="Auto-approved via quarterly script.",
)
# 6. Complete the cycle
await client.recertification.complete_cycle(
"marketing-analytics", cycle.id
)
print("Cycle completed.")