Skip to content

Access-Grid/accessgrid-rb

Repository files navigation

AccessGrid Logo

AccessGrid is a Ruby 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

Add this line to your application's Gemfile:

gem 'accessgrid'

And then execute:

$ bundle install

Or install it yourself as:

$ gem install accessgrid

Quick Start

require 'accessgrid'

account_id = ENV['ACCOUNT_ID']
secret_key = ENV['SECRET_KEY']

client = AccessGrid.new(account_id, secret_key)

API Reference

Access Cards

Issue a new card

card = client.access_cards.issue(
  card_template_id: card_template_id,
  employee_id: "123456789",
  tag_id: "DDEADB33FB00B5",
  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: Time.now.utc.iso8601(3),
  expiration_date: 3.months.from_now.utc.iso8601(3),
  employee_photo: "[image_in_base64_encoded_format]",
  title: "Engineering Manager",
  metadata: {
    "department": "engineering",
    "badge_type": "contractor"
  }
)

# Provision is an alias for issue (for backwards compatibility)
card = client.access_cards.provision(
  card_template_id: card_template_id,
  employee_id: "123456789",
  # ...other parameters
)

puts "Install URL: #{card.url}"

Get a card

card = client.access_cards.get(card_id: "0xc4rd1d")

puts "Card ID: #{card.id}"
puts "State: #{card.state}"
puts "Full Name: #{card.full_name}"
puts "Install URL: #{card.install_url}"
puts "Expiration Date: #{card.expiration_date}"
puts "Card Number: #{card.card_number}"
puts "Site Code: #{card.site_code}"
puts "Devices: #{card.devices.length}"
puts "Metadata: #{card.metadata}"

Update a card

card = client.access_cards.update(
  "0xc4rd1d", 
  {
    employee_id: "987654321",
    full_name: "Updated Employee Name",
    classification: "contractor",
    expiration_date: "2025-02-22T21:04:03.664Z",
    employee_photo: "[image_in_base64_encoded_format]"
  }
)

List cards

# List all cards for a template
cards = client.access_cards.list("template_id")

# List cards filtered by state
active_cards = client.access_cards.list("template_id", "active")

Manage card states

# Suspend a card
client.access_cards.suspend("0xc4rd1d")

# Resume a card
client.access_cards.resume("0xc4rd1d")

# Unlink a card
client.access_cards.unlink("0xc4rd1d")

# Delete a card
client.access_cards.delete("0xc4rd1d")

Enterprise Console

Create a template

template = client.console.create_template(
  name: "Employee Access Pass",
  platform: "apple",
  use_case: "employee_badge",
  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(
  "0xd3adb00b5",
  {
    name: "Updated Employee NFC key",
    watch_count: 2,
    iphone_count: 3,
    support_info: {
      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("0xd3adb00b5")

Get event logs

# New method
logs = client.console.get_logs(
  "0xd3adb00b5",
  {
    device: "mobile", # "mobile" or "watch"
    start_date: (Time.now - 30*24*60*60).iso8601,
    end_date: Time.now.iso8601,
    event_type: "install"
  }
)

# Legacy method still works
events = client.console.event_log(
  card_template_id: "0xd3adb00b5",
  filters: {
    device: "mobile", # "mobile" or "watch"
    start_date: (Time.now - 30*24*60*60).iso8601,
    end_date: Time.now.iso8601,
    event_type: "install"
  }
)

List pass template pairs

response = client.console.list_pass_template_pairs(page: 1, per_page: 20)

response['card_template_pairs'].each do |pair|
  puts "#{pair.name} (#{pair.id})"
  puts "  iOS: #{pair.ios_template&.name}"
  puts "  Android: #{pair.android_template&.name}"
end

puts response['pagination'] # { "current_page" => 1, "total_pages" => 5, ... }

List ledger items

response = client.console.list_ledger_items(
  page: 1,
  per_page: 50,
  start_date: '2025-01-01T00:00:00Z',
  end_date: '2025-06-30T23:59:59Z'
)

response['ledger_items'].each do |item|
  puts "#{item.kind}: #{item.amount} (#{item.created_at})"

  if item.access_pass
    puts "  Pass: #{item.access_pass.full_name} (#{item.access_pass.state})"
    if item.access_pass.pass_template
      puts "  Template: #{item.access_pass.pass_template.name}"
    end
  end
end

puts response['pagination'] # { "current_page" => 1, "total_pages" => 3, ... }

iOS In-App Provisioning Preflight

response = client.console.ios_preflight(
  card_template_id: "0xt3mp14t3-3x1d",
  access_pass_ex_id: "0xp455-3x1d"
)

puts "Provisioning Credential ID: #{response.provisioning_credential_identifier}"
puts "Sharing Instance ID: #{response.sharing_instance_identifier}"
puts "Card Template ID: #{response.card_template_identifier}"
puts "Environment ID: #{response.environment_identifier}"

Webhooks

Create a webhook

webhook = client.console.webhooks.create(
  name: 'Production',
  url: 'https://example.com/webhooks',
  subscribed_events: ['ag.access_pass.issued']
)

puts "Webhook created: #{webhook.id}"
puts "Private key: #{webhook.private_key}"

List webhooks

webhooks = client.console.webhooks.list

webhooks.each do |webhook|
  puts "ID: #{webhook.id}, Name: #{webhook.name}"
end

Delete a webhook

client.console.webhooks.delete('abc123')

HID Organizations

Create an HID org

org = client.console.hid.orgs.create(
  name: 'My Org',
  full_address: '1 Main St, NY NY',
  phone: '+1-555-0000',
  first_name: 'Ada',
  last_name: 'Lovelace'
)

puts "Created org: #{org.name} (ID: #{org.id})"
puts "Slug: #{org.slug}"

List HID orgs

orgs = client.console.hid.orgs.list

orgs.each do |org|
  puts "Org ID: #{org.id}, Name: #{org.name}, Slug: #{org.slug}"
end

Activate an HID org

result = client.console.hid.orgs.activate(
  email: 'admin@example.com',
  password: 'hid-password-123'
)

puts "Completed registration for org: #{result.name}"
puts "Status: #{result.status}"

Landing Pages

List landing pages

landing_pages = client.console.list_landing_pages

landing_pages.each do |page|
  puts "ID: #{page.id}, Name: #{page.name}, Kind: #{page.kind}"
  puts "  Password Protected: #{page.password_protected}"
  puts "  Logo URL: #{page.logo_url}" if page.logo_url
end

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
)

puts "Landing page created: #{landing_page.id}"
puts "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"
)

puts "Landing page updated: #{landing_page.id}"
puts "Name: #{landing_page.name}"

Credential Profiles

List credential profiles

profiles = client.console.credential_profiles.list

profiles.each do |profile|
  puts "ID: #{profile.id}, Name: #{profile.name}, AID: #{profile.aid}"
end

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' }
  ]
)

puts "Profile created: #{profile.id}"
puts "AID: #{profile.aid}"

Configuration

The SDK can be configured with a custom API endpoint:

client = AccessGrid.new(
  account_id, 
  secret_key, 
  'https://api.staging.accessgrid.com' # Use a different API endpoint
)

Error Handling

The SDK throws specific errors for various scenarios:

  • AccessGrid::AuthenticationError - Invalid credentials
  • AccessGrid::ResourceNotFoundError - Requested resource not found
  • AccessGrid::ValidationError - Invalid parameters
  • AccessGrid::AccessGridError - Base exception for AccessGrid-specific errors
  • AccessGrid::Error - Generic API errors

Example error handling:

begin
  card = client.access_cards.provision(
    # ... parameters
  )
rescue AccessGrid::ValidationError => e
  puts "Invalid parameters: #{e.message}"
rescue AccessGrid::Error => e
  puts "API error: #{e.message}"
end

Requirements

  • Ruby 2.19 or higher

Security

The SDK automatically handles:

  • Request signing using HMAC-SHA256
  • Secure payload encoding
  • Authentication headers
  • HTTPS communication

Never expose your secret_key in client-side code. Always use environment variables or a secure configuration management system.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/access-grid/accessgrid-rb.

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
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.list_ledger_items() / console.ledger_items() 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
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
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

License

The gem is available as open source under the terms of the MIT License.

About

Ruby wrapper for AccessGrid

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors