certynix
Official Ruby SDK for the Certynix Trust Infrastructure API.
Installation
Add to your Gemfile:
gem 'certynix'
Then run:
bundle install
Or install directly:
gem install certynix
Requires Ruby 3.1+.
Quick Start
require 'certynix'
client = Certynix::Client.new(ENV['CERTYNIX_API_KEY']) # cnx_live_sk_... or cnx_test_sk_...
# Register an asset by SHA-256 hash
asset = client.assets.register(
hash_sha256: 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',
filename: 'contract-2024.pdf'
)
puts "#{asset.id} — #{asset.status}"
puts asset.is_first_registrant ? 'First registrant!' : 'Already registered'
# Public verification (no auth required)
result = client.verify.by_hash(asset.hash)
puts result.match ? 'Verified' : 'Not found'
puts result.first_registrant.organization_name
Authentication
# Production
client = Certynix::Client.new('cnx_live_sk_...')
# Sandbox (auto-detected from key prefix cnx_test_sk_)
client = Certynix::Client.new('cnx_test_sk_...')
# Automatically uses https://sandbox.certynix.com
# Custom options
client = Certynix::Client.new(
'cnx_live_sk_...',
base_url: 'https://api.staging.certynix.com',
timeout: 30,
max_retries: 3
)
Resources
Assets
# Register by hash
asset = client.assets.register(
hash_sha256: 'abc123...',
filename: 'document.pdf',
source_url: 'https://example.com/document.pdf',
metadata: { author: 'John Doe' }
)
# Register by URL (Certynix downloads and hashes)
asset = client.assets.register(
source_url: 'https://example.com/document.pdf',
filename: 'document.pdf'
)
# Register batch (up to 1,000 assets)
batch = client.assets.register_batch(
assets: [
{ hash_sha256: 'abc...', filename: 'file1.pdf' },
{ hash_sha256: 'def...', filename: 'file2.pdf' }
]
)
puts "#{batch.batch_id} — #{batch.status}"
# Get by ID
asset = client.assets.get('ast_abc123')
# List (Enumerable — all pages iterated automatically)
client.assets.list(limit: 50).each do |asset|
puts "#{asset.id} — #{asset.status}"
end
# List with filters
verified = client.assets.list(status: 'verified').to_a
# Lazy with limit
first_10 = client.assets.list.lazy.first(10)
# Delete (soft delete — history preserved)
client.assets.delete('ast_abc123')
Verification (public — no API key required)
# Verify by SHA-256 hash
result = client.verify.by_hash(
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
)
puts result.match ? 'Verified' : 'Not found'
puts result.first_registrant.organization_name
# Verify by asset ID
result = client.verify.by_asset_id('ast_abc123')
# Verify by URL
result = client.verify.by_url('https://example.com/document.pdf')
Webhooks
# Create webhook
webhook = client.webhooks.create(
url: 'https://example.com/webhook',
events: ['asset.created', 'asset.verified', 'exposure.alert.created']
)
# Store webhook.signing_secret securely — shown only once!
# List
client.webhooks.list.each do |webhook|
puts "#{webhook.id} — #{webhook.url}"
end
# Update
webhook = client.webhooks.update('wh_abc123', active: false)
# Delete
client.webhooks.delete('wh_abc123')
# Validate signature (in your webhook handler)
begin
event = Certynix::Webhooks.validate_signature(
raw_body: request.body.read,
signature: request.headers['X-Certynix-Signature'],
secret: ENV['CERTYNIX_WEBHOOK_SECRET']
)
puts event.type
puts event.payload.inspect
rescue Certynix::WebhookSignatureError => e
render plain: 'Invalid signature', status: :bad_request
rescue Certynix::WebhookReplayError => e
render plain: 'Replay attack detected', status: :bad_request
end
Exposure Alerts
# List active alerts
client.alerts.list(resolved: false).each do |alert|
puts "[#{alert.severity}] #{alert.description}"
end
API Keys
# Create — value shown only once!
key = client.api_keys.create(name: 'Production App')
puts key.key_value # cnx_live_sk_... — store immediately!
# List
client.api_keys.list.each do |key|
puts "#{key.name} — #{key.prefix}"
end
# Revoke
client.api_keys.revoke('key_abc123')
Audit Logs
client.audit_logs.list(limit: 50).each do |log|
puts "#{log.action} by #{log.actor_id} at #{log.created_at}"
end
# Filter by action
client.audit_logs.list(action: 'asset.created').each do |log|
puts log.resource_id
end
Trust Score
score = client.trust_score.get
puts "Score: #{score.score}/100"
puts "Identity: #{score.components.identity}"
puts "Security: #{score.components.security}"
puts "Behavior: #{score.components.behavior}"
puts "Assets: #{score.components.assets}"
score.penalties.each do |penalty|
puts "Penalty: #{penalty.description} (-#{penalty.points})"
end
Error Handling
require 'certynix'
begin
asset = client.assets.get('ast_notfound')
rescue Certynix::NotFoundError => e
puts "Not found: #{e.}"
puts "Code: #{e.code}"
puts "Request ID: #{e.request_id}"
rescue Certynix::RateLimitError => e
puts "Rate limited. Retry after: #{e.retry_after}s"
rescue Certynix::AuthenticationError => e
puts "Invalid API key"
rescue Certynix::ServerError => e
puts "Server error: #{e.}"
rescue Certynix::NetworkError => e
puts "Network error: #{e.}"
end
Pagination
All list methods return a Paginator that includes Ruby's Enumerable:
# Iterate all pages automatically
client.assets.list(limit: 100).each do |asset|
puts asset.id
end
# Collect all into array
assets = client.assets.list.to_a
# Lazy enumeration (stops fetching when you stop iterating)
first_10 = client.assets.list.lazy.first(10)
# Map, select, reduce
verified_ids = client.assets.list
.select { |a| a.status == 'verified' }
.map(&:id)
Retry Policy
The SDK automatically retries on transient errors (via faraday-retry):
| Scenario | Retried |
|---|---|
429 Too Many Requests |
Yes — respects Retry-After |
500, 502, 503, 504 |
Yes — exponential backoff + jitter |
| Network errors | Yes |
400, 401, 403, 404, 409 |
No |
Default: 3 retries, max 60s backoff.
Webhook Signature Validation
# Rails example
class WebhooksController < ApplicationController
skip_before_action :verify_authenticity_token
def certynix
event = Certynix::Webhooks.validate_signature(
raw_body: request.body.read,
signature: request.headers['X-Certynix-Signature'],
secret: Rails.application.credentials.certynix_webhook_secret
)
case event.type
when 'asset.created'
AssetCreatedJob.perform_later(event.payload)
when 'asset.verified'
AssetVerifiedJob.perform_later(event.payload)
when 'exposure.alert.created'
AlertCreatedJob.perform_later(event.payload)
end
head :ok
rescue Certynix::WebhookSignatureError, Certynix::WebhookReplayError
head :bad_request
end
end
Testing
bundle install
bundle exec rspec
License
MIT