All pages
Powered by GitBook
1 of 4

Loading...

Loading...

Loading...

Loading...

Fair usage policy

At Unifize, our goal is to provide a robust and scalable platform. This Fair Usage Policy (FUP) aims to ensure optimal performance and availability of our APIs for all users by preventing misuse that could impair the functioning of our systems.

General Usage Guidelines

Efficient Use

Clients are expected to use our APIs responsibly. To maintain system health and fairness, API usage should ideally not exceed five times the transaction volume conducted by users within their organization.

Monitoring

Unifize will actively monitor usage patterns to manage system performance and detect excessive use.

Acceptable Usage Limits

Transaction-Based Limits

The acceptable limit for API transactions is set at up to five times the average number of transactions conducted by users within the same organization. This is to ensure that API usage is proportional and does not overshadow the activities of individual users.

Enforcement Measures

If an integration consistently exceeds this limit, Unifize reserves the right to throttle API usage or reject API calls to preserve system integrity and ensure equal resource distribution.

Prohibited Actions

Excessive Polling

Clients should avoid excessive polling of API endpoints. Implement appropriate caching to reduce the need for frequent calls.

Bulk Requests

Avoid sending large volumes of requests in a short period, as this may negatively impact system performance.

Use intelligent polling intervals and caching to minimize the need for repetitive API calls.

Employ exponential backoff strategies when managing API rate limits and handling error responses to avoid overwhelming the system.

Repeated violations of these transaction volumes may result in temporary restrictions or permanent limits on API access, ensuring fair resource allocation among all users.

This policy is subject to periodic review and adjustment based on business needs and system performance. Significant changes will be communicated to all users to ensure transparency.

If your integration requires higher transaction volumes or if you have concerns regarding this policy, please reach out to Unifize Support for assistance or to discuss potential custom solutions.

Usage

This section provides everything you need to get started with your Unifize API integration—from spinning up test environments to understanding usage limits and best practices. Whether you’re testing endpoints or scaling requests, these resources ensure smooth development.

Use this section to test confidently, build responsibly, and get started quickly. It’s the foundation for a successful Unifize API integration.

Best Practices

Polling and Caching Strategies

Backoff Mechanisms

Consequences of Non-Compliance

Adaptability and Review

Contact and Support

Explore

Understand rate limits, best practices, and guidelines to ensure responsible API usage.

Safely experiment with the API in a sandbox before going live.

Your first API call, made easy. Set up authentication and hit your first endpoint in minutes.

Fair Usage Policy
Testing Environment
Quickstart

Testing environment

This document provides third-party integrators with comprehensive information on how to effectively utilize our testing environments to ensure smooth integration and deployment of your applications with Unifize's systems.

What is a Testing Environment?

At Unifize, our testing environments are standalone organizations (orgs) created specifically for integration purposes, distinct from typical "sandbox" environments. While sandboxes often share settings and data structures with production environments, each Unifize testing environment is an entirely separate org that can be configured as a clone of your live environment upon request.

This ensures that you can test integrations with settings and data that mirror your actual production setup but without affecting live operations.

Requesting a Testing Environment

To request access to a testing environment,

Contact Us

Reach out to your assigned customer success representative, or contact our support team at support@unifize.com.

Request Details

Specify your requirements, including whether you need a clone of the live environment. This configuration helps ensure that the testing environment closely resembles your production environment for accurate testing.

Once your testing environment is set up,

Authenticate using the provided credentials specific to your testing org. Note that these credentials will differ from those used in the live environment.

Configure your test scenarios using the unique identifiers (e.g., Process ID, Org ID, etc.) relevant to your testing org. Remember, these IDs will differ from the live environment.

Execute your integration scenarios as you would in the live environment. Utilize the extensive logging and debugging tools available within the testing environment to monitor interactions and tweak performances.

Before deploying your integration to the live environment,

Ensure all references to Unifize identifiers such as Org ID, Process ID, Field ID, and others are correctly mapped to their corresponding live environment values. This step is crucial to prevent mismatches and errors in the live system.

Switch from the testing API credentials to the live environment API credentials, ensuring all API interactions are authenticated correctly.

Conduct thorough tests to confirm that all integrations function as expected with the correctly mapped IDs and API keys.

Contact your customer success representative to guide you through the necessary steps and approvals needed for transitioning from the testing environment to the live environment.

If you encounter issues during integration,

Contact your customer success representative or our API support team for real-time troubleshooting.

Refer to the API documentation for common issues and troubleshooting tips.

We welcome feedback on API functionalities and support requests for future features. While not all feature requests may be immediately implemented, they are essential for our continuous improvement.

How to Test with Mock Data

Initialize your Environment

Mock Data Configuration

Testing

Preparing for Live Deployment

ID Mapping

Modifying Credentials

Validation

Push to Production

Troubleshooting

Immediate Assistance

Support Documentation

Feedback and Improvements

Quickstart

Make your first API call!

Before you get started with this section, pleasure ensure you have the following 3 pieces of data with you:

  1. Your App ID

  2. Your App's RSA private key

Introduction

The Unifize APIs are crafted following RESTful standards, ensuring that interaction with resources is consistent and intuitive. The APIs are endpoint-driven and typically represent distinct resources, allowing for clear, organized, and efficient communication between systems.

All interactions are managed through the JSON data format, which necessitates setting the content type to application/json. This requirement is enforced for both request and response bodies unless otherwise specified, facilitating seamless data exchange and integration with various applications. Such consistent data handling simplifies interaction and enhances compatibility with different platforms and programming environments.

Authentication and Authorization

Authentication is a necessary aspect of utilizing the Unifize APIs and is implemented via app tokens. These tokens are generated according to the guidelines detailed in the page.

Additionally, authorization is handled via a permissions framework, which grants granular control over access levels and operations. Permissions can be set initially during app creation and remain flexible, allowing for modifications as the needs of the application evolve. This dual-layered security model ensures that the Unifize APIs provide robust protection for sensitive operations and data.

Organizations

Central to Unifize's architecture are logical entities known as "Organizations," which help partition and manage resources within the system. The Org Id of these organizations must be specified during the initial token request process. This token, once embedded within a JWT, eliminates the need for repeatedly specifying the Org Id in further API calls, streamlining authentication processes and reducing complexity.

You can read more about Organizations in the page.

To do this using your preferred programming language, the only requirements are:

  • A library to mint JWTs

  • A library to read/parse PEM files

  • A library to make network requests

Below are some examples in commonly used programming languages.

Also see the

Prerequisites:

Prerequisites:

Add the following dependencies to your project:

  • io.jsonwebtoken:jjwt-api

io.jsonwebtoken:jjwt-impl
  • io.jsonwebtoken:jjwt-jackson (or another JSON processor implementation)

  • The Org ID corresponding to your testing/live environment

    For (1) and (2), revisit the Authentication section.

    For (3), revisit the Testing Environment section.

    Test it out

    App Tokens
    API Reference.
    Concepts and Terminologies
    npm install jsonwebtoken axios
    const fs = require('fs');
    const jwt = require('jsonwebtoken');
    const axios = require('axios');
    
    /**
     * Loads a private key from a PEM file
     * @param {string} filePath - Path to the PEM file
     * @returns {string} Private key as a string
     */
    function loadPrivateKeyFromPem(filePath) {
      return fs.readFileSync(filePath, 'utf8');
    }
    
    /**
     * Generates a JWT token with the given app ID and signed using the private key
     * @param {number} appId - The application ID to use as issuer
     * @param {string} privateKeyPath - Path to the private key PEM file
     * @returns {string} Signed JWT token
     */
    function generateJwt(appId, privateKeyPath) {
      // Load the private key
      const privateKey = loadPrivateKeyFromPem(privateKeyPath);
      
      // Get current time in seconds
      const nowSeconds = Math.floor(Date.now() / 1000);
      
      // Create the payload
      const payload = {
        iss: appId.toString(),
        iat: nowSeconds,
        exp: nowSeconds + 600
      };
      
      // Sign the JWT
      return jwt.sign(payload, privateKey, { algorithm: 'RS256' });
    }
    
    /**
     * Exchanges the JWT for an access token
     * @param {string} jwtToken - The JWT token to exchange
     * @param {number} orgId - The organization ID
     * @returns {Promise} Promise resolving to the access token response
     */
    async function exchangeJwtForAccessToken(jwtToken, orgId) {
      try {
        const response = await axios.post(
          `https://api.example.com/application/installation/${orgId}/token`,
          { token: jwtToken },
          {
            headers: {
              'Authorization': `Bearer ${jwtToken}`,
              'Content-Type': 'application/json'
            }
          }
        );
        return response.data;
      } catch (error) {
        throw error;
      }
    }
    
    /**
     * Makes an API call with the access token in the Authorization header
     * @param {string} accessToken - The access token to use for authorization
     * @returns {Promise} Promise resolving to the API response
     */
    async function makeApiCall(accessToken) {
      try {
        const response = await axios.get('https://api.example.com/', {
          headers: {
            'Authorization': `Bearer ${accessToken}`
          }
        });
        return response;
      } catch (error) {
        throw error;
      }
    }
    
    /**
     * Main function to demonstrate the JWT generation, token exchange, and API call
     */
    async function main() {
      // Example usage
      const appId = 12345;
      const orgId = 67890;
      const privateKeyPath = 'path/to/private_key.pem';
      
      try {
        // Generate JWT
        const jwt = generateJwt(appId, privateKeyPath);
        console.log('JWT generated successfully');
        
        // Exchange JWT for access token
        const tokenResponse = await exchangeJwtForAccessToken(jwt, orgId);
        const accessToken = tokenResponse.access_token;
        const expiresAt = tokenResponse.expires_at;
        console.log(`Access token received, expires at: ${expiresAt}`);
        
        // Make API call with access token
        const response = await makeApiCall(accessToken);
        
        // Print response
        console.log(`Status code: ${response.status}`);
        console.log(`Response body:`, response.data);
      } catch (error) {
        console.error('Error:', error.message);
        if (error.response) {
          console.error('Response status:', error.response.status);
          console.error('Response data:', error.response.data);
        }
      }
    }
    
    // Execute the main function
    main();
    pip install pyjwt requests cryptography
    import jwt
    import time
    import requests
    from pathlib import Path
    from cryptography.hazmat.primitives.serialization import load_pem_private_key
    from cryptography.hazmat.backends import default_backend
    
    
    def load_private_key_from_pem(file_path):
        """
        Loads a private key from a PEM file
        
        Args:
            file_path (str): Path to the PEM file
            
        Returns:
            cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey: The private key object
        """
        pem_data = Path(file_path).read_bytes()
        # Load the private key - passing None for password if the key is not encrypted
        private_key = load_pem_private_key(pem_data, password=None, backend=default_backend())
        return private_key
    
    
    def generate_jwt(app_id, private_key_path):
        """
        Generates a JWT token with the given app ID and signed using the private key
        
        Args:
            app_id (int): The application ID to use as issuer
            private_key_path (str): Path to the private key PEM file
            
        Returns:
            str: Signed JWT token
        """
        # Load the private key
        private_key = load_private_key_from_pem(private_key_path)
        
        # Get current time in seconds
        now_seconds = int(time.time())
        
        # Create the payload
        payload = {
            'iss': str(app_id),
            'iat': now_seconds,
            'exp': now_seconds + 600
        }
        
        # Sign the JWT
        return jwt.encode(payload, private_key, algorithm='RS256')
    
    
    def exchange_jwt_for_access_token(jwt_token, org_id):
        """
        Exchanges the JWT for an access token
        
        Args:
            jwt_token (str): The JWT token to exchange
            org_id (int): The organization ID
            
        Returns:
            dict: The access token response containing access_token and expires_at
        """
        headers = {
            'Authorization': f'Bearer {jwt_token}',
            'Content-Type': 'application/json'
        }
        
        payload = {
            'token': jwt_token
        }
        
        response = requests.post(
            f'https://api.example.com/application/installation/{org_id}/token',
            headers=headers,
            json=payload
        )
        
        response.raise_for_status()  # Raise an exception for HTTP errors
        return response.json()
    
    
    def make_api_call(access_token):
        """
        Makes an API call with the access token in the Authorization header
        
        Args:
            access_token (str): The access token to use for authorization
            
        Returns:
            requests.Response: The API response
        """
        headers = {
            'Authorization': f'Bearer {access_token}'
        }
        
        return requests.get('https://api.example.com/', headers=headers)
    
    
    def main():
        """
        Main function to demonstrate the JWT generation, token exchange, and API call
        """
        # Example usage
        app_id = 12345
        org_id = 67890
        private_key_path = 'path/to/private_key.pem'
        
        try:
            # Generate JWT
            jwt_token = generate_jwt(app_id, private_key_path)
            print("JWT generated successfully")
            
            # Exchange JWT for access token
            token_response = exchange_jwt_for_access_token(jwt_token, org_id)
            access_token = token_response['access_token']
            expires_at = token_response['expires_at']
            print(f"Access token received, expires at: {expires_at}")
            
            # Make API call with access token
            response = make_api_call(access_token)
            
            # Print response
            print(f"Status code: {response.status_code}")
            print(f"Response body: {response.text}")
            
        except Exception as e:
            print(f"Error: {str(e)}")
    
    
    if __name__ == "__main__":
        main()
    import java.io.IOException;
    import java.net.URI;
    import java.net.http.HttpClient;
    import java.net.http.HttpRequest;
    import java.net.http.HttpResponse;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.security.KeyFactory;
    import java.security.PrivateKey;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.time.Instant;
    import java.util.Base64;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    
    import io.jsonwebtoken.Jwts;
    import io.jsonwebtoken.SignatureAlgorithm;
    import io.jsonwebtoken.jackson.io.JacksonDeserializer;
    import io.jsonwebtoken.jackson.io.JacksonSerializer;
    import io.jsonwebtoken.io.Deserializer;
    import io.jsonwebtoken.io.Serializer;
    
    public class JwtApiClient {
        
        /**
         * Generates a JWT token with the given app ID and signed using the private key
         */
        public static String generateJwt(int appId, String privateKeyPath) throws Exception {
            // Load the private key from the PEM file
            PrivateKey privateKey = loadPrivateKeyFromPem(privateKeyPath);
            
            // Get current time
            long nowSeconds = Instant.now().getEpochSecond();
            
            // Build the JWT
            return Jwts.builder()
                    .setIssuer(String.valueOf(appId))
                    .setIssuedAt(new Date(nowSeconds * 1000))
                    .setExpiration(new Date((nowSeconds + 600) * 1000))
                    .signWith(privateKey, SignatureAlgorithm.RS256)
                    .compact();
        }
        
        /**
         * Exchanges the JWT for an access token
         */
        public static Map<String, Object> exchangeJwtForAccessToken(String jwt, int orgId) throws IOException, InterruptedException {
            HttpClient client = HttpClient.newHttpClient();
            
            // Create the JSON payload
            String jsonPayload = String.format("{\"token\":\"%s\"}", jwt);
            
            HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("https://api.example.com/application/installation/" + orgId + "/token"))
                    .header("Authorization", "Bearer " + jwt)
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(jsonPayload))
                    .build();
            
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
            
            if (response.statusCode() >= 400) {
                throw new IOException("Failed to exchange token: " + response.statusCode() + ", " + response.body());
            }
            
            // Parse the JSON response using the JJWT Jackson deserializer
            Deserializer<Map<String, ?>> deserializer = new JacksonDeserializer<>();
            return (Map<String, Object>) deserializer.deserialize(response.body().getBytes());
        }
        
        /**
         * Makes an API call to the root endpoint with the access token in the Authorization header
         */
        public static HttpResponse<String> makeApiCall(String accessToken) throws IOException, InterruptedException {
            HttpClient client = HttpClient.newHttpClient();
            
            HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("https://api.example.com/"))
                    .header("Authorization", "Bearer " + accessToken)
                    .GET()
                    .build();
            
            return client.send(request, HttpResponse.BodyHandlers.ofString());
        }
        
        /**
         * Loads an RSA private key from a PEM file
         */
        private static PrivateKey loadPrivateKeyFromPem(String filePath) throws Exception {
            String key = new String(Files.readAllBytes(Paths.get(filePath)));
            
            // Remove PEM format headers and footers and decode
            String privateKeyPEM = key
                    .replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s", "");
            
            byte[] encoded = Base64.getDecoder().decode(privateKeyPEM);
            
            // Create the private key
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
            return keyFactory.generatePrivate(keySpec);
        }
        
        public static void main(String[] args) {
            // Example usage
            int appId = 12345;
            int orgId = 67890;
            String privateKeyPath = "path/to/private_key.pem";
            
            try {
                // 1. Generate JWT
                String jwt = generateJwt(appId, privateKeyPath);
                System.out.println("JWT generated successfully");
                
                // 2. Exchange JWT for access token
                Map<String, Object> tokenResponse = exchangeJwtForAccessToken(jwt, orgId);
                String accessToken = (String) tokenResponse.get("access_token");
                String expiresAt = (String) tokenResponse.get("expires_at");
                System.out.println("Access token received, expires at: " + expiresAt);
                
                // 3. Make API call with access token
                HttpResponse<String> response = makeApiCall(accessToken);
                
                // 4. Print response
                System.out.println("Status code: " + response.statusCode());
                System.out.println("Response body: " + response.body());
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }