NAV Navbar
shell javascript
  • Introduction
  • Authentication
  • Device Registration
  • Scanner Management
  • Events
  • Errors
  • Introduction

    Web Site

    https://twain.hazybits.com
    

    API Endpoint

    https://twain-api.hazybits.com
    

    Welcome to the TWAIN Cloud API! You can use our API to register, review, and control scanners, associated with your TWAIN Cloud account. It is like Google Print, but for scanners :)

    You can do all kinds of amazing things with scanners remotely - acquire documents, process them in the cloud and retrieve right to your device (PC, Mac, mobile phone - doesn't matter). API is based on HTTP / web sockets, so can be accessed virtually from any platform.

    You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right.

    Please feel free to follow development progress on GitHub and join the discussion! Documentation for the project is hosted on GitHub as well - so in case of any mistakes or suggestions please submit an issue there.

    TWAIN Direct vs TWAIN Cloud

    TWAIN Direct is an industry standard created by TWAIN Working Group. It defines a protocol of communication between scanner device and client application. By design, TWAIN Direct does not require scanner drivers, i.e. allows 'direct' connection between application and scanner device. Primary goal of the standard is to make life of scanner vendors and application writers easier by introducing cross-platform, technology agnostic language of communication.

    Please check out TWAIN Direct web site for additional details.

    TWAIN Cloud is a standard

    TWAIN Cloud is an extension of TWAIN Direct that defines a standard and secure way for scanner devices to be used over Internet. This capability enables a number of interesting scenarios, not available before:

    TWAIN Cloud is an industry standard in its own right which TWAIN Working Group owns. Having said that, TWAIN Cloud implementation that HazyBits hosts on https://twain.hazybits.com web site is an implementation of the standard, one of the many possible.

    The primary goal of this implementation is to demonstrate what is possible to achieve with modern image capture technologies and how they can change your business processes.

    Authentication

    To authorize a request, pass access token in Authorization header::

    curl "api_endpoint_here"
      -H "Authorization: {accessToken}"
    

    Make sure to replace accessToken placeholder with the correct token.

    HazyBits TWAIN Cloud implementation relies on OAuth2 authorization framework to exchange user's Facebook access token to a pair of TWAIN Cloud tokens:

    Access token should be passed along with every request in Authorization HTTP header. Access token has an expiration time (1 hour by default) after which it should be refreshed using refresh token.

    Refresh token can be used only once to get a new pair of access/refresh tokens.

    Login endpoint

    Start login flow using the following request:

    curl "https://twain-api.hazybits.com/signin"
    
    $.ajax({
        method: 'GET',
        url: apiEndpoint + '/signin'
    })
    

    This endpoint begins OAuth2 login flow. There is a series of GET requests, connected through HTTP redirects:

    Diagram below illustrates the whole authentication process:

    Login Flow

    HTTP Request

    GET https://twain-api.hazybits.com/signin

    Query Parameters

    Parameter Description
    origin Origin
    query URL-encoded query string to add to the redirect URL.

    Refresh token endpoint

    Refresh access token using the following request:

    curl "https://twain-api.hazybits.com/refresh/{refreshToken}"
    
    $.ajax({
        method: 'POST',
        url: apiEndpoint + `/refresh/${refreshToken}`
    })
    

    Make sure to replace refreshToken placeholder with the correct token.

    The above command returns JSON structured like this:

    {
      "accessToken": "{renewed access token}", 
      "refreshToken": "{new refresh token}"
    }
    

    Since access tokens have a short lifetime (1 hour by default), they need to be refreshed by an application. To request access token refresh, application needs to exchange refresh token to a new pair of access / refresh tokens.

    HTTP Request

    GET https://twain-api.hazybits.com/refresh/{refreshToken}

    URL Parameters

    Parameter Description
    refreshToken Previously issued refresh token for exchange.

    Device Registration

    Overview

    Scanner device should be registered with TWAIN Cloud and associated with a user account before it can be used. From scanner device standpoint the flow looks as follows:

    Registration Flow

    The whole process is more complex since it requires user interaction. Complete registration sequence is illustrated on the diagram below:

    Registration Sequence

    Start registration flow

    curl "https://twain-api.hazybits.com/register"
    
    $.ajax({
        method: 'POST',
        url: apiEndpoint + '/register',
        contentType: 'application/json',
        data: JSON.stringify({
          // TBD
        })
    });
    

    The above command returns JSON structured like this:

    {
      "registrationToken": "<registration token>",
      "pollingUrl": "<polling URL>",
      "inviteUrl": "<invite URL>"
    }
    

    This endpoint begins registration process.

    HTTP Request

    POST https://twain-api.hazybits.com/register

    Request Payload

    TBD (scanner attributes)

    Response Payload

    Parameter Description
    registrationToken Secret token that should be provided by user to claim the scanner.
    pollingUrl URL to be used by scanner device to poll registration status.
    inviteUrl URL to be used by user to claim the scanner.

    Poll Registration Status

    curl "https://twain-api.hazybits.com/poll?scannerId={scannerId}"
    
    $.ajax({
        method: 'GET',
        url: apiEndpoint + '/poll?scannerId={scannerId}',
    });
    

    The above command returns JSON structured like this:

    { 
      "success": true, 
      "accessToken": "{accessToken}",
      "refreshToken": "{refreshToken}"
    }
    

    In case of any error, response is as follows:

    {
      "success": false,
      "message": "Error message",
    }
    

    Scanner device use this endpoint to poll TWAIN Cloud server and check if registration process is complete (user claimed the device successfully).

    It is recommended to poll the server with some delay before retries. 5 seconds delay is reasonable default.

    HTTP Request

    GET https://twain-api.hazybits.com/poll?scannerId={scannerId}

    Query Parameters

    Parameter Description
    scannerId Unique ID of the scanner to check registration status for.

    Response Payload

    Success response payload:

    Parameter Description
    success True in case of success registration.
    accessToken Access token to be used by scanner to authorize calls to TWAIN Cloud endpoints.
    refreshToken Refresh token to be used to get a new pair of access/refresh tokens.

    Error response payload:

    Parameter Description
    success False in case incomplete registration.
    message Technical message related to the request.

    Claim Device

    curl "https://twain-api.hazybits.com/claim"
      -H "Authorization: <access token>"
    
    // TODO: add headers and body
    $.ajax({
        method: 'POST',
        url: apiEndpoint + '/claim',
        contentType: 'application/json',
        data: JSON.stringify({ 
          scannerId: '{scannerId}',
          registrationToken: '{registrationToken}'
        })
    });
    

    The above command returns JSON structured like this:

    {
      // TBD
    }
    

    This endpoint completes registration flow and associates scanner with a user (using information from Authorization header).

    Once registration is complete,

    HTTP Request

    POST https://twain-api.hazybits.com/claim

    Request Payload

    Parameter Description
    scannerId Unique ID of the scanner to be claimed.
    registrationToken Registration token that was provided during scanner registration.

    Response Payload

    TBD (scanner attributes)

    Scanner Management

    Get list of registered scanners

    curl "https://twain-api.hazybits.com/scanners"
    
    $.ajax({
        method: 'GET',
        url: apiEndpoint + '/scanners',
    });
    

    The above command returns JSON structured like this:

    [
      {
        "id": "fb7e3325-4d3a-4c9c-a6b4-9b83d2551951",
        "manufacturer": "TWAIN",
        // TBD
      },
    
      // ...
      // the rest of scanners, registered with the cloud.
    ]
    

    In case of any error, response is as follows:

    TBD
    

    User may retrieve all scanners registered in TWAIN Cloud.

    HTTP Request

    GET https://twain-api.hazybits.com/scanners

    Query Parameters

    Parameter Description

    Response Payload

    Success response payload:

    Parameter Description

    Error response payload:

    Parameter Description

    Get scanner information

    curl "https://twain-api.hazybits.com/scanners/{scannerId}"
    
    $.ajax({
        method: 'GET',
        url: apiEndpoint + '/scanners/{scannerId}',
    });
    

    The above command returns JSON structured like this:

    TBD
    

    In case of any error, response is as follows:

    TBD
    

    User may delete registered scanner from the cloud using this endpoint.

    HTTP Request

    GET https://twain-api.hazybits.com/scanners/{scannerId}

    Query Parameters

    Parameter Description
    scannerId Unique ID of the scanner to get information about.

    Response Payload

    Success response payload:

    Parameter Description

    Error response payload:

    Parameter Description

    Delete scanner

    curl -X "DELETE" "https://twain-api.hazybits.com/scanners/{scannerId}"
    
    $.ajax({
        method: 'DELETE',
        url: apiEndpoint + '/scanners/{scannerId}',
    });
    

    The above command returns JSON structured like this:

    TBD
    

    In case of any error, response is as follows:

    TBD
    

    User may delete registered scanner from the cloud using this endpoint.

    HTTP Request

    DELETE https://twain-api.hazybits.com/scanners/{scannerId}

    Query Parameters

    Parameter Description
    scannerId Unique ID of the scanner to delete from the cloud.

    Response Payload

    Success response payload:

    Parameter Description

    Error response payload:

    Parameter Description

    Events

    TWAIN Cloud is asynchronous by design - operations may take a while to complete, so results of the operations are delivered to the clients asynchronously using events.

    TWAIN Direct relies on long polling technique for eventing which is a reasonable choice for modern reliable LAN environments. The same technique can't be applied to TWAIN Cloud though, therefore another eventing mechanism is required.

    MQTT is the eventing protocol that is used in TWAIN Cloud. It is a mature and effective protocol with large number of client libraries available for virtually every platform. MQTT is supported by all major cloud vendors as well, so TWAIN Cloud implementors don't need to create this infrastructure.

    Errors

    TWAIN Cloud API uses the following error codes:

    Error Code Meaning
    400 Bad Request -- Your request is invalid.
    401 Unauthorized -- Your authentication token is invalid.
    500 Internal Server Error -- We had a problem with our server. Try again later.