AccessGrid SDK
A Python SDK for interacting with the AccessGrid.com API. This SDK provides a simple interface for managing NFC key cards and enterprise templates. Full docs at https://www.accessgrid.com/docs
Installation
pip install accessgrid
Quick Start
from accessgrid import AccessGrid
account_id = os.environ.get('ACCOUNT_ID')
secret_key = os.environ.get('SECRET_KEY')
client = AccessGrid(account_id, secret_key)
API Reference
Access Cards
Provision a new card
card = client.access_cards.provision(
card_template_id="0xd3adb00b5",
employee_id="123456789",
card_number="123456",
site_code="100",
full_name="Employee name",
email="employee@yourwebsite.com",
phone_number="+19547212241",
classification="full_time",
department="Engineering",
location="San Francisco",
site_name="HQ Building A",
workstation="4F-207",
mail_stop="MS-401",
company_address="123 Main St, San Francisco, CA 94105",
start_date="2025-01-31T22:46:25.601Z",
expiration_date="2025-04-30T22:46:25.601Z",
employee_photo="[image_in_base64_encoded_format]",
title="Engineering Manager",
metadata={
"department": "engineering",
"badge_type": "contractor"
}
)
Update a card
card = client.access_cards.update(
card_id="0xc4rd1d",
employee_id="987654321",
full_name="Updated Employee Name",
classification="contractor",
department="Marketing",
location="New York",
site_name="NYC Office",
workstation="2F-105",
mail_stop="MS-200",
company_address="456 Broadway, New York, NY 10013",
expiration_date="2025-02-22T21:04:03.664Z",
employee_photo="[image_in_base64_encoded_format]",
title="Senior Developer"
)
List NFC keys / Access passes
# List all cards for a template
cards = client.access_cards.list(template_id="0xd3adb00b5")
for card in cards:
print(card) # Outputs: AccessCard(name='Employee Name', id='0xc4rd1d', state='active')
# Filter cards by state
active_cards = client.access_cards.list(template_id="0xd3adb00b5", state="active")
Manage card states
# Suspend a card
client.access_cards.suspend(card_id="0xc4rd1d")
# Resume a card
client.access_cards.resume(card_id="0xc4rd1d")
# Unlink a card
client.access_cards.unlink(card_id="0xc4rd1d")
# Delete a card
client.access_cards.delete(card_id="0xc4rd1d")
Enterprise Console
Create a template
template = client.console.create_template(
name="Employee Access Pass",
platform="apple",
use_case="corporate_id",
protocol="desfire",
allow_on_multiple_devices=True,
watch_count=2,
iphone_count=3,
background_color="#FFFFFF",
label_color="#000000",
label_secondary_color="#333333",
support_url="https://help.yourcompany.com",
support_phone_number="+1-555-123-4567",
support_email="support@yourcompany.com",
privacy_policy_url="https://yourcompany.com/privacy",
terms_and_conditions_url="https://yourcompany.com/terms",
metadata={
"version": "2.1",
"approval_status": "approved"
}
)
Update a template
template = client.console.update_template(
card_template_id="0xd3adb00b5",
name="Updated Employee NFC key",
allow_on_multiple_devices=True,
watch_count=2,
iphone_count=3,
support_url="https://help.yourcompany.com",
support_phone_number="+1-555-123-4567",
support_email="support@yourcompany.com",
privacy_policy_url="https://yourcompany.com/privacy",
terms_and_conditions_url="https://yourcompany.com/terms"
)
Read a template
template = client.console.read_template(card_template_id="0xd3adb00b5")
Delete a template
client.console.delete_template("0xd3adb00b5")
Publish a template
result = client.console.publish_template(card_template_id="0xd3adb00b5")
print(f"Template {result.id} status: {result.status}")
# status is one of: "publishing" (already in flight), "in-review" (Apple
# queued), or "ready" (Android immediate)
Reveal a SmartTap private key
Fetches the template's SmartTap private key, decrypted client-side. The SDK generates a fresh ephemeral P-256 keypair per call, submits the public half, and decrypts the server's response — you get the plaintext PEM back without touching any crypto.
reveal = client.console.reveal_smart_tap(card_template_id="0xd3adb00b5")
print(f"Key version: {reveal.key_version}")
print(f"Collector ID: {reveal.collector_id}")
print(f"Fingerprint: {reveal.fingerprint}")
print(reveal.private_key) # PEM — store in your reader/collector key vault
The server enforces single-use on pubkey fingerprint and rate-limits to 1 per minute per account. The SDK uses a fresh keypair every call, so single-use is satisfied automatically.
Get event logs
from datetime import datetime, timedelta
events = client.console.event_log(
card_template_id="0xd3adb00b5",
filters={
"device": "mobile", # "mobile" or "watch"
"start_date": (datetime.now() - timedelta(days=30)).isoformat(),
"end_date": datetime.now().isoformat(),
"event_type": "install"
}
)
iOS In-App Provisioning Preflight
response = client.console.ios_preflight(
card_template_id="0xt3mp14t3-3x1d",
access_pass_ex_id="0xp455-3x1d"
)
print(f"Provisioning Credential ID: {response.provisioningCredentialIdentifier}")
print(f"Sharing Instance ID: {response.sharingInstanceIdentifier}")
print(f"Card Template ID: {response.cardTemplateIdentifier}")
print(f"Environment ID: {response.environmentIdentifier}")
List ledger items
from datetime import datetime, timezone, timedelta
start_date = (datetime.now(timezone.utc) - timedelta(days=30)).isoformat()
end_date = datetime.now(timezone.utc).isoformat()
result = client.console.ledger_items(
page=1,
per_page=50,
start_date=start_date,
end_date=end_date
)
for item in result['ledger_items']:
print(f"Amount: {item['amount']}, Kind: {item['kind']}, Date: {item['created_at']}")
if item.get('access_pass'):
print(f" Access Pass: {item['access_pass']['ex_id']}")
if item['access_pass'].get('pass_template'):
print(f" Card Template: {item['access_pass']['pass_template']['ex_id']}")
Card Template Pairs
Create a card template pair
Both templates must be published (status: ready) and unpaired. Valid protocol
combinations are both SEOS, or Apple DESFire with Google Smart Tap.
pair = client.console.create_pass_template_pair(
name="Employee Badge Pair",
apple_card_template_id="0xapplet3mp14t3",
google_card_template_id="0xgoogl3t3mp14t3"
)
print(f"Created pair: {pair.name} (ID: {pair.id})")
List card template pairs
result = client.console.list_pass_template_pairs(page=1, per_page=50)
for pair in result['card_template_pairs']:
print(f"{pair.name} (ID: {pair.id})")
if pair.ios_template:
print(f" iOS: {pair.ios_template.id}")
if pair.android_template:
print(f" Android: {pair.android_template.id}")
Landing Pages
List landing pages
landing_pages = client.console.list_landing_pages()
for page in landing_pages:
print(f"ID: {page.id}, Name: {page.name}, Kind: {page.kind}")
print(f" Password Protected: {page.password_protected}")
if page.logo_url:
print(f" Logo URL: {page.logo_url}")
Create a landing page
landing_page = client.console.create_landing_page(
name="Miami Office Access Pass",
kind="universal",
additional_text="Welcome to the Miami Office",
bg_color="#f1f5f9",
allow_immediate_download=True
)
print(f"Landing page created: {landing_page.id}")
print(f"Name: {landing_page.name}, Kind: {landing_page.kind}")
Update a landing page
landing_page = client.console.update_landing_page(
landing_page_id="0xlandingpage1d",
name="Updated Miami Office Access Pass",
additional_text="Welcome! Tap below to get your access pass.",
bg_color="#e2e8f0"
)
print(f"Landing page updated: {landing_page.id}")
print(f"Name: {landing_page.name}")
Credential Profiles
List credential profiles
profiles = client.console.credential_profiles.list()
for profile in profiles:
print(f"ID: {profile.id}, Name: {profile.name}, AID: {profile.aid}")
Create a credential profile
profile = client.console.credential_profiles.create(
name='Main Office Profile',
app_name='KEY-ID-main',
keys=[
{'value': 'your_32_char_hex_master_key_here'},
{'value': 'your_32_char_hex__read_key__here'}
]
)
print(f"Profile created: {profile.id}")
print(f"AID: {profile.aid}")
Delete a credential profile
client.console.credential_profiles.delete('cp-1')
Webhooks
Create a webhook
webhook = client.console.webhooks.create(
name='Production',
url='https://example.com/webhooks',
subscribed_events=['ag.access_pass.issued']
)
print(f"Webhook created: {webhook.id}")
print(f"Private key: {webhook.private_key}")
List webhooks
webhooks = client.console.webhooks.list()
for webhook in webhooks:
print(f"ID: {webhook.id}, Name: {webhook.name}")
Delete a webhook
client.console.webhooks.delete('abc123')
Verify a webhook
result = client.console.webhooks.verify('abc123')
print(f"Webhook {result.id} verified: {result.verified}")
# verified is True when already verified, or False when a verification
# handshake has just been initiated
HID Organizations
Create a HID organization
org = client.console.hid.orgs.create(
name='My Organization',
full_address='1 Main St, NY NY',
phone='+1-555-0000',
first_name='Ada',
last_name='Lovelace'
)
print(f"Created org: {org.name} (ID: {org.id})")
print(f"Slug: {org.slug}")
Complete HID org registration
After creating an organization, complete the registration with credentials from your HID email:
result = client.console.hid.orgs.activate(
email='admin@example.com',
password='hid-password-123'
)
print(f"Completed registration for org: {result.name}")
print(f"Status: {result.status}")
List all HID organizations
orgs = client.console.hid.orgs.list()
for org in orgs:
print(f"Org ID: {org.id}, Name: {org.name}, Slug: {org.slug}")
Configuration
The SDK can be configured with custom options:
client = AccessGrid(
account_id,
secret_key
)
Error Handling
The SDK throws errors for various scenarios including:
- Missing required credentials
- API request failures
- Invalid parameters
- Server errors
Example error handling:
try:
card = client.access_cards.provision(
# ... parameters
)
except AccessGridError as error:
print(f'Failed to provision card: {str(error)}')
Requirements
- Python 3.7 or higher
- Required packages:
- requests
- cryptography
- python-dateutil
Security
The SDK automatically handles:
- Request signing using HMAC-SHA256
- Secure payload encoding
- Authentication headers
- HTTPS communication
Never expose your secret_key in source code. Always use environment variables or a secure configuration management system.
License
MIT License - See LICENSE file for details.
Feature Matrix
| Endpoint | Method | Supported |
|---|---|---|
| POST /v1/key-cards | access_cards.issue() |
Y |
| GET /v1/key-cards/{id} | access_cards.get() |
Y |
| PATCH /v1/key-cards/{id} | access_cards.update() |
Y |
| GET /v1/key-cards | access_cards.list() |
Y |
| POST /v1/key-cards/{id}/suspend | access_cards.suspend() |
Y |
| POST /v1/key-cards/{id}/resume | access_cards.resume() |
Y |
| POST /v1/key-cards/{id}/unlink | access_cards.unlink() |
Y |
| POST /v1/key-cards/{id}/delete | access_cards.delete() |
Y |
| POST /v1/console/card-templates | console.create_template() |
Y |
| PUT /v1/console/card-templates/{id} | console.update_template() |
Y |
| GET /v1/console/card-templates/{id} | console.read_template() |
Y |
| DELETE /v1/console/card-templates/{id} | console.delete_template() |
Y |
| POST /v1/console/card-templates/{id}/publish | console.publish_template() |
Y |
| POST /v1/console/card-templates/{id}/smart-tap/reveal | console.reveal_smart_tap() |
Y |
| GET /v1/console/card-templates/{id}/logs | console.get_logs() / console.event_log() |
Y |
| GET /v1/console/card-template-pairs | console.list_pass_template_pairs() |
Y |
| POST /v1/console/card-template-pairs | console.create_pass_template_pair() |
Y |
| POST /v1/console/card-templates/{id}/ios_preflight | console.ios_preflight() |
Y |
| GET /v1/console/ledger-items | console.ledger_items() |
Y |
| GET /v1/console/landing-pages | console.list_landing_pages() |
Y |
| POST /v1/console/landing-pages | console.create_landing_page() |
Y |
| PUT /v1/console/landing-pages/{id} | console.update_landing_page() |
Y |
| GET /v1/console/credential-profiles | console.credential_profiles.list() |
Y |
| POST /v1/console/credential-profiles | console.credential_profiles.create() |
Y |
| DELETE /v1/console/credential-profiles/{id} | console.credential_profiles.delete() |
Y |
| GET /v1/console/webhooks | console.webhooks.list() |
Y |
| POST /v1/console/webhooks | console.webhooks.create() |
Y |
| DELETE /v1/console/webhooks/{id} | console.webhooks.delete() |
Y |
| POST /v1/console/webhooks/{id}/verify | console.webhooks.verify() |
Y |
| POST /v1/console/hid/orgs | console.hid.orgs.create() |
Y |
| POST /v1/console/hid/orgs/activate | console.hid.orgs.activate() |
Y |
| GET /v1/console/hid/orgs | console.hid.orgs.list() |
Y |
Metadata
Release files for accessgrid 0.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| accessgrid-0.6.0.tar.gz | 28.8 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| accessgrid-0.6.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 55.0 kB
Release files / accessgrid-0.6.0.tar.gz
| Download URL | accessgrid-0.6.0.tar.gz |
|---|---|
| Size | 28.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c0ffa02d39247b6e1efc4110ff75ca0f060d2ee4db98d49379c44bd5f85c2fd8
|
|
BLAKE2b-256 checksum How to use checksums |
987cf3892c7fa2a63a8c50f6101e85c1b334c6367492a2b06b3c4789f0599f6f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / accessgrid-0.6.0-py3-none-any.whl
| Download URL | accessgrid-0.6.0-py3-none-any.whl |
|---|---|
| Size | 26.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a2c58432d9f2ad37efe0bdc1e1bee8ae5a507d125aeb180d90a008aa81c0b580
|
|
BLAKE2b-256 checksum How to use checksums |
0a5a97e08e72a826d8401cabd2a661453c7c7435403a858cbc539a78a1f213d1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Security for accessgrid 0.6.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
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.
To learn more about protecting yourself from malicious actors, visit our package security documentation.