TL;DR
HIPAA compliance for APIs requires strict safeguards for Protected Health Information (PHI): encryption in transit and at rest, audit logging, access controls, and Business Associate Agreements (BAAs). This guide shows how to implement a HIPAA-focused API architecture, authentication, authorization, audit trails, and compliance verification.
Introduction
Healthcare data breaches cost an average of $10.93 million per incident. If you build healthcare applications, API security is not optional: it is part of meeting HIPAA (Health Insurance Portability and Accountability Act) requirements.
Unauthorized API and application access is involved in 79% of healthcare data breaches. A properly designed HIPAA-compliant API architecture helps prevent unauthorized access, creates an auditable record of PHI activity, and protects patient privacy.
This guide covers:
- PHI classification and the minimum necessary standard
- BAAs and vendor review
- MFA, JWTs, and role-based authorization
- TLS and encryption at rest
- Audit logging and retention
- Input validation, rate limiting, and error handling
- Deployment and risk-assessment checklists
π‘ Design secure endpoints, validate encryption requirements, audit access patterns, and document compliance controls in one workspace with Apidog. Share API specifications with your compliance team and maintain audit-ready documentation.
What Is HIPAA and Why Does It Matter for APIs?
HIPAA is a US federal law that establishes standards for protecting sensitive patient health information. For APIs, the HIPAA Security Rule applies to electronic Protected Health Information (ePHI) created, received, maintained, or transmitted by your application.
Who Must Comply
| Entity type | Examples | API implications |
|---|---|---|
| Covered entities | Healthcare providers, health plans, clearinghouses | Direct HIPAA liability |
| Business associates | API providers, cloud services, software vendors | BAA required; direct liability |
| Subcontractors | Subprocessors, downstream API services | BAA required |
Key HIPAA Rules for APIs
Privacy Rule
- Governs the use and disclosure of PHI
- Requires the minimum necessary standard
- Provides patient access rights
- Defines authorization requirements
Security Rule
- Requires safeguards for ePHI
- Access controls
- Audit controls
- Integrity controls
- Transmission security
Breach Notification Rule
- Defines incident-response requirements
- Requires risk-assessment documentation
- Includes a 60-day notification window
- Requires mitigation procedures
API Architecture Overview
A HIPAA-oriented API stack should place controls at every layer:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β HIPAA-COMPLIANT API STACK β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β CLIENT βββββΆβ API GATEWAY βββββΆβ DATABASE β β
β β (App) β β β β (Encrypted) β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β β β β
β βΌ βΌ βΌ β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β OAuth 2.0 β β WAF + Rate β β Audit β β
β β + MFA β β Limiting β β Logging β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β
β Encrypt data in transit with TLS 1.3+ and at rest with AES-256 β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Getting Started: Build the Compliance Foundation
Step 1: Execute Business Associate Agreements
Before your API handles PHI:
- Identify every vendor that can access, process, store, transmit, back up, or log PHI.
- Execute a BAA with each applicable vendor.
- Document downstream subprocessors.
- Review BAAs annually and whenever your architecture changes.
Common vendors that may require BAAs:
- Cloud hosting providers such as AWS, GCP, and Azure
- Database providers
- Logging and SIEM services
- Backup providers
- API gateways
- Monitoring and alerting tools
Do not use the following for PHI unless an appropriate BAA and configuration are in place:
- Standard Google Analytics
- Free-tier cloud services
- Personal email accounts
- Non-healthcare Slack channels
Step 2: Classify API Data
Create a data inventory before implementing endpoints. Mark each field as PHI, then apply the appropriate controls.
| Data type | Classification | Protection level |
|---|---|---|
| Patient name + date of birth | PHI | Full HIPAA controls |
| Medical record number | PHI | Full HIPAA controls |
| Diagnosis codes (ICD-10) | PHI | Full HIPAA controls |
| Treatment notes | PHI | Full HIPAA controls |
| Appointment times without patient identifiers | Not PHI | Standard controls |
| Aggregated, de-identified data | Not PHI | Standard controls |
Step 3: Apply the Minimum Necessary Standard
Avoid endpoints that return an entire patient object by default. Use a server-side allowlist and return only the fields required for the request.
// BAD: Returns all patient data
app.get('/api/patients/:id', async (req, res) => {
const patient = await db.patients.findById(req.params.id);
res.json(patient);
});
// GOOD: Return only allowlisted fields
app.get('/api/patients/:id', async (req, res) => {
const requestedFields = req.query.fields?.split(',') || ['id', 'name'];
const allowedFields = ['id', 'name', 'dateOfBirth'];
const fields = requestedFields.filter(field => allowedFields.includes(field));
const patient = await db.patients.findById(req.params.id);
const filtered = Object.fromEntries(
Object.entries(patient).filter(([key]) => fields.includes(key))
);
res.json(filtered);
});
Do not let a client choose arbitrary database fields. Validate requested fields against an endpoint-specific allowlist.
Technical Safeguards Implementation
Access Control: Authentication
Use strong authentication for every user who can access PHI. This example verifies a password, verifies an MFA code, issues a short-lived JWT, and records the event.
const crypto = require('crypto');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');
class HIPAAAuthService {
async authenticate(username, password, mfaCode, requestContext) {
// 1. Verify credentials
const user = await this.getUserByUsername(username);
if (!user) throw new Error('Invalid credentials');
const validPassword = await bcrypt.compare(password, user.passwordHash);
if (!validPassword) throw new Error('Invalid credentials');
// 2. Verify MFA using TOTP
const validMFA = this.verifyTOTP(user.mfaSecret, mfaCode);
if (!validMFA) throw new Error('Invalid MFA code');
// 3. Issue a short-lived token for PHI access
const token = jwt.sign(
{
sub: user.id,
role: user.role,
mfa_verified: true
},
process.env.JWT_SECRET,
{ expiresIn: '15m' }
);
// 4. Record the authentication event
await this.auditLog('AUTH_SUCCESS', {
userId: user.id,
ip: requestContext.ip
});
return { token, expiresIn: 900 };
}
verifyTOTP(secret, token) {
const period = 30;
const digits = 6;
const now = Math.floor(Date.now() / 1000);
const counter = Math.floor(now / period);
const buffer = Buffer.alloc(8);
buffer.writeUInt32BE(0, 0);
buffer.writeUInt32BE(counter, 4);
const hmac = crypto.createHmac('sha1', secret).update(buffer).digest();
const offset = hmac[hmac.length - 1] & 0x0f;
const code = (
((hmac[offset] & 0x7f) << 24) |
((hmac[offset + 1] & 0xff) << 16) |
((hmac[offset + 2] & 0xff) << 8) |
(hmac[offset + 3] & 0xff)
) % Math.pow(10, digits);
return code.toString().padStart(digits, '0') === token;
}
}
Implementation checklist:
- Require MFA for PHI-capable accounts.
- Keep PHI access tokens short-lived.
- Store signing keys securely.
- Record successful and failed authentication attempts.
- Add refresh-token rotation if your architecture uses refresh tokens.
Access Control: Authorization
Authentication identifies the caller. Authorization determines whether that caller can access a specific resource.
Start with role-based access control (RBAC):
const ROLES = {
ADMIN: 'admin',
PROVIDER: 'provider',
NURSE: 'nurse',
BILLING: 'billing',
PATIENT: 'patient'
};
const PERMISSIONS = {
[ROLES.ADMIN]: ['read:all', 'write:all', 'delete:all'],
[ROLES.PROVIDER]: [
'read:patients',
'write:patients',
'read:labs',
'write:orders'
],
[ROLES.NURSE]: ['read:patients', 'write:vitals', 'read:labs'],
[ROLES.BILLING]: ['read:billing', 'read:patients:limited'],
[ROLES.PATIENT]: ['read:self', 'write:self']
};
Enforce permissions with middleware:
const authorize = (...requiredPermissions) => {
return async (req, res, next) => {
const user = req.user;
const userPermissions = PERMISSIONS[user.role] || [];
const hasPermission = requiredPermissions.every(permission =>
userPermissions.includes(permission)
);
if (!hasPermission) {
await auditLog('AUTHZ_DENIED', {
userId: user.id,
action: req.method,
path: req.path,
required: requiredPermissions
});
return res.status(403).json({
error: 'Insufficient permissions'
});
}
next();
};
};
Apply authentication and authorization before the route handler:
app.get(
'/api/patients/:id/records',
authenticate,
authorize('read:patients'),
getPatientRecords
);
RBAC alone is not enough for patient records. Also verify the provider-to-patient relationship or whether the patient owns the requested record.
Encryption in Transit
Require HTTPS for all API communication and configure TLS 1.3.
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem'),
ca: fs.readFileSync('ca-cert.pem'),
minVersion: 'TLSv1.3',
ciphers: [
'TLS_AES_256_GCM_SHA384',
'TLS_CHACHA20_POLY1305_SHA256',
'TLS_AES_128_GCM_SHA256'
].join(':'),
honorCipherOrder: true
};
const server = https.createServer(options, app);
Redirect HTTP traffic to HTTPS:
app.use((req, res, next) => {
if (!req.secure) {
return res.redirect(`https://${req.headers.host}${req.url}`);
}
next();
});
Add HTTP Strict Transport Security (HSTS):
app.use((req, res, next) => {
res.setHeader(
'Strict-Transport-Security',
'max-age=31536000; includeSubDomains; preload'
);
next();
});
Encryption at Rest
Encrypt stored PHI and manage encryption keys with a managed key service such as AWS KMS, GCP KMS, or Azure Key Vault.
The following example uses AES-256-GCM, which provides encryption and integrity protection:
const crypto = require('crypto');
class EncryptionService {
constructor(key) {
// In production, use a managed KMS or vault for key management.
this.key = crypto.scryptSync(key, 'salt', 32);
this.algorithm = 'aes-256-gcm';
}
encrypt(plaintext) {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(this.algorithm, this.key, iv);
let encrypted = cipher.update(plaintext, 'utf8', 'hex');
encrypted += cipher.final('hex');
return {
encryptedData: encrypted,
iv: iv.toString('hex'),
authTag: cipher.getAuthTag().toString('hex')
};
}
decrypt(encryptedData, iv, authTag) {
const decipher = crypto.createDecipheriv(
this.algorithm,
this.key,
Buffer.from(iv, 'hex')
);
decipher.setAuthTag(Buffer.from(authTag, 'hex'));
let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
}
Encrypt PHI fields before persistence and decrypt only when an authorized request needs them:
class PatientRecord {
constructor(db, encryptionService) {
this.db = db;
this.encryption = encryptionService;
}
async create(data) {
const encryptedData = {
...data,
ssn: this.encryption.encrypt(data.ssn),
diagnosis: this.encryption.encrypt(data.diagnosis),
treatmentNotes: this.encryption.encrypt(data.treatmentNotes)
};
await this.db.patients.insert(encryptedData);
await auditLog('PHI_CREATED', { recordType: 'patient' });
}
async findById(id) {
const record = await this.db.patients.findById(id);
return {
...record,
ssn: this.encryption.decrypt(
record.ssn.encryptedData,
record.ssn.iv,
record.ssn.authTag
),
diagnosis: this.encryption.decrypt(
record.diagnosis.encryptedData,
record.diagnosis.iv,
record.diagnosis.authTag
),
treatmentNotes: this.encryption.decrypt(
record.treatmentNotes.encryptedData,
record.treatmentNotes.iv,
record.treatmentNotes.authTag
)
};
}
}
Audit Controls Implementation
Comprehensive Audit Logging
Your API needs a record of who accessed PHI, what they did, when it occurred, and whether the action succeeded.
const winston = require('winston');
const auditLogger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.File({
filename: '/var/log/hipaa-audit/audit.log',
maxsize: 52428800,
maxFiles: 365
}),
new winston.transports.Http({
host: 'siem.internal',
path: '/api/logs',
ssl: true
})
]
});
Use a single audit-log function so every route produces consistent events:
const auditLog = async (event, details) => {
const logEntry = {
timestamp: new Date().toISOString(),
event,
actor: details.userId,
action: details.action,
resource: details.resource,
outcome: details.outcome || 'SUCCESS',
ipAddress: details.ip,
userAgent: details.userAgent,
details: details.metadata
};
auditLogger.info(logEntry);
await db.auditLogs.insert(logEntry);
};
Add middleware that captures PHI-related endpoint activity:
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', async () => {
const duration = Date.now() - start;
const isPHIEndpoint =
req.path.includes('/patients') || req.path.includes('/records');
if (!isPHIEndpoint) return;
await auditLog('API_ACCESS', {
userId: req.user?.id || 'anonymous',
action: req.method,
resource: req.path,
outcome: res.statusCode < 400 ? 'SUCCESS' : 'FAILURE',
ip: req.ip,
userAgent: req.headers['user-agent'],
metadata: {
duration,
statusCode: res.statusCode,
queryParams: Object.keys(req.query)
}
});
});
next();
});
Avoid putting unnecessary PHI in logs. Log identifiers and event metadata needed for investigation, but do not log complete patient records, access tokens, passwords, or sensitive request bodies.
Required Audit Events
| Event type | What to log | Retention |
|---|---|---|
| Authentication | Success/failure, MFA status, IP | 6 years |
| Authorization | Denied access attempts | 6 years |
| PHI access | Who accessed what and when | 6 years |
| PHI modification | Before/after values | 6 years |
| PHI deletion | What was deleted and by whom | 6 years |
| System changes | Configuration changes, new users | 6 years |
| Security events | Failed requests, rate limits | 6 years |
Audit Report Generation
Generate reports that compliance teams can review without manually querying raw logs.
const generateAuditReport = async (startDate, endDate, options = {}) => {
const query = {
timestamp: {
$gte: new Date(startDate),
$lte: new Date(endDate)
}
};
if (options.userId) {
query.actor = options.userId;
}
if (options.eventType) {
query.event = options.eventType;
}
const logs = await db.auditLogs.find(query).sort({ timestamp: 1 });
return {
reportPeriod: { start: startDate, end: endDate },
generatedAt: new Date().toISOString(),
summary: {
totalEvents: logs.length,
uniqueUsers: new Set(logs.map(log => log.actor)).size,
failures: logs.filter(log => log.outcome === 'FAILURE').length,
phiAccess: logs.filter(log => log.event === 'PHI_ACCESS').length
},
events: logs
};
};
Schedule weekly reporting:
cron.schedule('0 0 * * 1', async () => {
const end = new Date();
const start = new Date(end.getTime() - 7 * 24 * 60 * 60 * 1000);
const report = await generateAuditReport(start, end);
await sendToComplianceTeam(report);
});
API Security Best Practices
Input Validation
Validate every path parameter, query parameter, header, and request body field. Do not pass client input directly into database queries.
const {
body,
param,
validationResult
} = require('express-validator');
const validatePatientRequest = [
body('firstName')
.trim()
.notEmpty()
.matches(/^[a-zA-Z\s'-]+$/)
.withMessage('Invalid first name format')
.isLength({ max: 50 }),
body('dateOfBirth')
.isISO8601()
.withMessage('Invalid date format')
.custom(value => new Date(value) < new Date())
.withMessage('Date of birth must be in the past'),
body('ssn')
.optional()
.matches(/^\d{3}-\d{2}-\d{4}$/)
.withMessage('Invalid SSN format'),
body('email')
.optional()
.isEmail()
.normalizeEmail(),
param('id')
.isUUID()
.withMessage('Invalid patient ID format'),
(req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({
error: 'Validation failed',
details: errors.array()
});
}
next();
}
];
Rate Limiting
Apply stricter limits to authentication endpoints and broader limits to general API routes.
const rateLimit = require('express-rate-limit');
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5,
message: { error: 'Too many authentication attempts' },
standardHeaders: true,
legacyHeaders: false,
handler: async (req, res) => {
await auditLog('RATE_LIMIT_EXCEEDED', {
userId: req.body.username,
ip: req.ip,
endpoint: 'auth'
});
res.status(429).json({ error: 'Too many attempts' });
}
});
const apiLimiter = rateLimit({
windowMs: 60 * 1000,
max: 100,
message: { error: 'Rate limit exceeded' }
});
app.use('/api/auth', authLimiter);
app.use('/api', apiLimiter);
Error Handling
Return generic client errors and log diagnostic details internally. Never include PHI or implementation details in error responses.
app.use((err, req, res, next) => {
console.error('Error:', {
message: err.message,
stack: err.stack,
path: req.path,
user: req.user?.id
});
res.status(err.status || 500).json({
error: 'An error occurred processing your request',
requestId: req.id
});
});
Never expose the following in API errors:
- Stack traces
- Database schema details
- Internal IP addresses
- User counts
- PHI
- Access tokens or secrets
Common HIPAA API Violations and How to Avoid Them
Violation: Inadequate Access Controls
Scenario: Any authenticated user can retrieve any patient record.
// BAD: Authentication alone does not authorize access
app.get('/api/patients/:id', async (req, res) => {
const patient = await db.patients.findById(req.params.id);
res.json(patient);
});
Fix: Verify that the requester owns the record or has a documented provider relationship with the patient.
app.get('/api/patients/:id', async (req, res) => {
const patient = await db.patients.findById(req.params.id);
// Patient accesses their own record
if (req.user.id === patient.userId) {
return res.json(patient);
}
// Provider accesses an assigned patient's record
const assignment = await db.providerAssignments.findOne({
providerId: req.user.id,
patientId: patient.id
});
if (assignment) {
return res.json(patient);
}
await auditLog('UNAUTHORIZED_ACCESS_ATTEMPT', {
userId: req.user.id,
patientId: patient.id
});
res.status(403).json({ error: 'Access denied' });
});
Violation: Missing Audit Logs
Scenario: There is no record of who accessed patient data.
Fix: Record all PHI access, authorization failures, changes, deletions, and security events. Store logs in append-only storage and retain them for six years.
Violation: Unencrypted Data Transmission
Scenario: The API accepts plain HTTP connections.
Fix: Require HTTPS and add HSTS.
app.use((req, res, next) => {
if (!req.secure && process.env.NODE_ENV === 'production') {
return res.status(403).json({
error: `HTTPS required. Connect via https://${req.headers.host}`
});
}
res.setHeader(
'Strict-Transport-Security',
'max-age=31536000; includeSubDomains'
);
next();
});
Violation: Excessive Data Exposure
Scenario: An endpoint returns a complete patient record when the client only needs a name.
Fix: Use field-level filtering and a safe projection.
app.get('/api/patients/:id', async (req, res) => {
const fields = req.query.fields?.split(',') || ['id', 'name'];
const projection = Object.fromEntries(fields.map(field => [field, 1]));
const patient = await db.patients.findById(req.params.id, projection);
res.json(patient);
});
In production, validate fields against an allowlist before building the projection.
Production Deployment Checklist
Before handling live PHI:
- [ ] Execute BAAs with all vendors
- [ ] Implement MFA for all users
- [ ] Enable TLS 1.3 for all endpoints
- [ ] Encrypt PHI at rest with AES-256
- [ ] Implement comprehensive audit logging
- [ ] Configure audit-log retention for 6+ years
- [ ] Configure RBAC and resource-level authorization
- [ ] Implement rate limiting
- [ ] Create an incident-response plan
- [ ] Document all security controls
- [ ] Conduct a security risk assessment
- [ ] Train staff on HIPAA requirements
- [ ] Schedule regular security audits
HIPAA Security Risk Assessment Template
System Overview
-
System name:
[API Name] -
PHI types handled:
[List] -
Data flow:
[Diagram]
Threat Assessment
| Threat | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Unauthorized access | Medium | High | MFA, RBAC |
| Data breach | Low | Critical | Encryption |
| Insider threat | Medium | High | Audit logs |
Control Testing
- [ ] Authentication bypass test
- [ ] Authorization bypass test
- [ ] SQL injection test
- [ ] XSS test
- [ ] Encryption verification
Sign-off
Security Officer: _______________ Date: _______
CTO: _______________ Date: _______
Real-World Use Cases
Telemedicine Platform API
A telehealth startup builds HIPAA-compliant video consultations.
- Challenge: Secure transmission of patient-provider video calls
- Solution: End-to-end encrypted WebRTC with a HIPAA-compliant signaling API
- Result: SOC 2 Type II certified, 500K+ consultations without breach
Key implementation details:
- JWT authentication with MFA
- Ephemeral room tokens that expire after a consultation
- No PHI stored in logs
- BAA with Twilio for video infrastructure
Patient Portal API
A hospital system modernizes patient access.
- Challenge: More than 20 legacy systems with inconsistent security
- Solution: A unified API gateway with centralized authentication and auditing
- Result: A single source of truth and simplified compliance reporting
Key implementation details:
- OAuth 2.0 with SMART on FHIR
- Centralized audit logging
- Field-level access control
- Automated breach detection
Health Data Integration Platform
A health technology company aggregates data from multiple EHRs.
- Challenge: Different security models across EHR vendors
- Solution: An abstraction layer with uniform HIPAA controls
- Result: More than 100 hospital integrations and zero compliance findings
Key implementation details:
- Data normalization with consistent encryption
- Per-tenant audit trails
- Automated BAA tracking
- Real-time compliance dashboards
Conclusion
HIPAA compliance for APIs requires deliberate architecture decisions around authentication, encryption, authorization, and audit logging.
Use this implementation checklist as your baseline:
- Execute BAAs with all vendors before handling PHI.
- Require MFA and implement role-based access control.
- Verify resource-level authorization for every PHI request.
- Encrypt data in transit with TLS 1.3 and at rest with AES-256.
- Log PHI access and retain audit records for six years.
- Apply the minimum necessary standard to every endpoint.
- Use Apidog to streamline API documentation and compliance workflows.
FAQ
What makes an API HIPAA-compliant?
An API is HIPAA-compliant when it implements the technical safeguards required to protect ePHI, including encryption, access controls, and audit logging. It must also support required administrative safeguards such as policies, staff training, and BAAs, plus applicable physical safeguards.
Do I need a BAA for my API?
Yes. If your API handles, processes, or stores PHI on behalf of a covered entity, you are a Business Associate and must sign a BAA. This also applies to cloud providers, API services, and subprocessors that handle PHI.
What encryption is required for HIPAA?
HIPAA requires encryption in transit and at rest. Use TLS 1.3 for API communication and AES-256 for stored data. Although encryption is technically addressable in the Security Rule, it is effectively required for compliance.
How long must HIPAA audit logs be retained?
HIPAA requires audit logs to be retained for six years from the date they were created or when the record was last in effect, whichever is later.
Can I use JWT for HIPAA-compliant authentication?
Yes. JWTs can be used when implemented securely: use short expiration periods, secure token storage, and refresh-token rotation. Combine JWT-based authentication with MFA for production systems that access PHI.
What is the minimum necessary standard?
The minimum necessary standard requires an API to expose only the PHI required for the intended purpose. Implement field-level filtering and purpose-based access controls to enforce it.
Do audit logs need to be encrypted?
Yes. Audit logs containing PHI should be encrypted at rest. Store them in append-only storage to help prevent tampering.
How do I handle breach notification?
If unauthorized PHI access occurs:
- Contain the breach.
- Assess risk using the four-factor test.
- Notify affected individuals within 60 days.
- Notify HHS immediately for breaches affecting 500 or more individuals.
- Document the incident, assessment, and mitigation steps.
Can I use cloud services for HIPAA workloads?
Yes, if the provider signs a BAA. AWS, GCP, and Azure offer HIPAA-eligible services. Configure each service according to the provider's HIPAA implementation guidance.
What penalties exist for HIPAA violations?
Civil penalties range from $100 to $50,000 per violation, with annual maximums of $1.5 million per violation category. Criminal penalties can include fines up to $250,000 and imprisonment for up to 10 years.
Top comments (0)