Authentication
Authentication
Section titled “Authentication”B2B integrations authenticate using OAuth 2.0 Client Credentials flow, the industry standard for server-to-server communication.
Step 1: Register Your Integration
Section titled “Step 1: Register Your Integration”Contact your Crinsutrack administrator to register your integration. You will receive:
- Client ID - Public identifier for your application
- Client Secret - Keep this secure, never expose in client-side code
Step 2: Request an Access Token
Section titled “Step 2: Request an Access Token”Exchange your client credentials for an access token:
curl -X POST https://api.crinsutrack.com/oauth/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials" \ -d "client_id=YOUR_CLIENT_ID" \ -d "client_secret=YOUR_CLIENT_SECRET"Response:
{ "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "expires_in": 3600}| Field | Description |
|---|---|
access_token | JWT access token for API requests |
token_type | Always Bearer |
expires_in | Token lifetime in seconds (1 hour) |
Step 3: Make API Requests
Section titled “Step 3: Make API Requests”Include the token in the Authorization header:
curl https://api.crinsutrack.com/api/subjects \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"Step 4: Token Renewal
Section titled “Step 4: Token Renewal”When the access token expires, request a new one using your client credentials. There is no refresh token in this flow.
curl -X POST https://api.crinsutrack.com/oauth/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials" \ -d "client_id=YOUR_CLIENT_ID" \ -d "client_secret=YOUR_CLIENT_SECRET"Python Client Example
Section titled “Python Client Example”import requestsfrom datetime import datetime, timedelta
class CrinsutrackClient: def __init__(self, client_id, client_secret): self.base_url = "https://api.crinsutrack.com" self.client_id = client_id self.client_secret = client_secret self.token = None self.token_expires = None
def authenticate(self): """Request access token using client credentials.""" response = requests.post( f"{self.base_url}/oauth/token", data={ "grant_type": "client_credentials", "client_id": self.client_id, "client_secret": self.client_secret }, headers={"Content-Type": "application/x-www-form-urlencoded"} ) response.raise_for_status() data = response.json() self.token = data["access_token"] self.token_expires = datetime.now() + timedelta(seconds=data["expires_in"] - 60)
def get_token(self): """Get valid access token, re-authenticating if needed.""" if not self.token or self.token_expires <= datetime.now(): self.authenticate() return self.token
def request(self, method, endpoint, **kwargs): headers = kwargs.pop("headers", {}) headers["Authorization"] = f"Bearer {self.get_token()}" return requests.request( method, f"{self.base_url}{endpoint}", headers=headers, **kwargs )
# Usageclient = CrinsutrackClient( client_id="your-client-id", client_secret="your-client-secret")
# Create a procedure requestrequest = client.request("POST", "/api/procedure-requests", json={ "type": "STORE", "facilityId": 1, "subjectCode": "SUBJ-2024-001", "sampleContainers": [ {"sampleContainerId": "VL-001", "description": "Vial 1"} ]}).json()
# Check request statusstatus = client.request("GET", f"/api/procedure-requests/{request['id']}").json()Security Best Practices
Section titled “Security Best Practices”- Never expose client secrets in frontend code, mobile apps, or public repositories
- Store secrets securely using environment variables, AWS Secrets Manager, or HashiCorp Vault
- Use HTTPS for all API requests
- Rotate secrets regularly - contact your administrator to generate new credentials
- Use separate credentials for development, staging, and production environments
- Monitor API usage - review access logs for unexpected activity
Revoking Access
Section titled “Revoking Access”To revoke your integration’s access:
- Contact your Crinsutrack administrator
- The client credentials will be invalidated
- All active tokens will be rejected
Troubleshooting
Section titled “Troubleshooting”| Error | Cause | Solution |
|---|---|---|
401 invalid_client | Invalid client ID or secret | Verify OAuth credentials |
401 Unauthorized | Invalid or expired token | Request a new token |
403 Forbidden | Operation not permitted for B2B | See Roles & Permissions |
429 Too Many Requests | Rate limit exceeded | Wait and retry with backoff |