EDH (1.4.7)

Download OpenAPI specification:Download

API Libraries › Entity API


EDH REST APIs for retrieving Entity data.

Note - this specification is subject to changes based on evolution of the APIs.

Release Notes

  • 1.4.7 (17 Mar 2025)

    • Data Items
      • Updated
        • Data sources under API Definitions to GoBusiness under licences
        • Max length to 255 for number, name, issuance-agency under licences
        • Max length to 500 for licensee.name under licences
        • licensee.nationality to non-mandatory under licences
      • Deprecated
        • licensee.nationality under licences
  • 1.4.6 (11 Dec 2024)

    • Data Items
      • Updated:
        • Max length to 2 for filing-agent.status.code under basic-profile
        • Max length to 65 for building of SG addresstype under addresses
        • period-end-date to non-mandatory under financials
        • Max length to 40 for chargee.chargee-entity.uen under charges
        • type, satisfaction.nature, satisfaction.status, satisfaction.date, variation.instrument-date to non-mandatory under charges
        • Max length to 40 for shareholding-entity.uen under shareholders and shareholders-list
        • Max length to 40 for subsidiary-entity.uen under subsidiaries-list
        • Max length to 40 for appointed-entity.uen under appointments
      • Deprecated
        • primary-activity-add-desc, secondary-activity-add-desc, company-authorized-capital-number, giro-indicator, folio-number under basic-profile
        • net-income-from-extraordinary-items, group-net-income-from-extraordinary-items under financials
        • chargee.desc, satisfaction.full-discharge-desc under charges
  • 1.4.5 (16 Aug 2024)

    • Data Items
      • Updated:
        • Category field under shareholders section
  • 1.4.4 (3 Oct 2023)

    • Data Items
      • Updated under corppass section:
        • Description for corppass-user.id-no
        • Corrected max length for corppass-user.id-type to 3 characters
        • Corrected max length for corppass-user.name to 100 characters
  • 1.4.3 (1 Dec 2022)

    • Updated category description under appointments section
  • 1.4.2 (3 March 2022)

    • Updated to reflect no nationality field for corppass-user under corppass section
    • Updated the entity samples to reflect no nationality field under corppass-user
  • 1.4.1 (11 September 2020)

    • Added active field for shareholders section
  • 1.4.0 (11 May 2020)

    • Added new builders and contractors section
  • 1.3.0 (20 April 2020)

    • Added new shareholders-list and subsidiaries-list section
  • 1.2.0 (10 October 2019)

    • Added new corppass section
  • 1.1.3 (17 September 2019)

    • gazette-list is removed from Declarations
  • 1.1.2 (22 August 2019)

    • Under Appointments, liquidator-company-type have been subsumed into category
    • Under Appointments, liquidator-type have been subsumed into position
    • Code tables have been updated to reflect this change
  • 1.1.1 (4 August 2019)

    • Added addresses for appointed-person and shareholder
  • 1.1.0 (8 July 2019)

    • Updated entity-name to 100 characters to support SG-DRM format
    • Added entity-long-name to reflect entity name more than 100 characters (capped at 256 characters)
  • 1.0.3 (26 June 2019)

    • Updated /(CONTEXT) from /edh to /gov
  • 1.0.2 (6 June 2019)

    • Remove realm parameter from request signing as it is not a required field
  • 1.0.1 (31 May 2019)

    • Updated NodeJS request sample
    • Enhanced entity-status and position codes fields to include relationship with entity-type
    • Updated response samples to show the enhanced entity-status and position codes
  • 1.0.0 (26 Apr 2019)

    • New security headers (see Security -> Request Signing)
    • Updates to Entity schema in entity; Note: Major changes in entity schema. Please see Understanding the Data Structure for details.
    • Response change to JWE wrapping JWS
  • 0.1.0 (22 Feb 2019)

    • Initial Draft Release

Releases and Compatibility

The RESTful API adopts Semantic Versioning 2.0.0 for releases, and every new release of the API increments the version numbers in the following format:

{MAJOR}.{MINOR}.{PATCH}
  1. {MAJOR} number introduces incompatible API changes with previous {MAJOR} number also resets {MINOR} to 0,
  2. {MINOR} number introduces new functionalities or information that are backward compatible also resets {PATCH} to 0, and
  3. {PATCH} number introduces bug fixes and remains backward compatible.

Pre-release or draft versions, when provided, are denoted by appended hypen - with a series of separate identifiers {LABEL}-{VERSION} following the {PATCH} number. Such releases are unstable and may not provide the intended compatibility with the specification in draft status.

Despite backward compatibility in {MINOR} or {PATCH} releases, API consumers are best to evaluate and determine their implementation does not disrupt use-case requirements.

Known Issues

Overview

Environments

The RESTful API provides both testing and live environments accessible over the Internet via HTTPS.

Consumers are to ensure firewall clearance on their edge network nodes for connecting to the APIs.

The convention used by API endpoints' URL are in the following format:

https://{ENV_DOMAIN_NAME}/{CONTEXT}/{VERSION}/{RESOURCE}
  • {ENV_DOMAIN_NAME} indicates EDH's API domain names - respectively:

    • sandbox.api.edh.gov.sg, or
    • test.api.edh.gov.sg, or
    • api.edh.gov.sg, following
  • /{CONTEXT}, indicates the context of the API call = /gov

  • /{VERSION} indicates the endpoint's release {MAJOR} version number path - for this release = /v1

  • /{RESOURCE} indicates the API resource path name.

Any additional query string parameters are appended as needed.

Available Environments

1. Sandbox Environment

The sandbox environment is used for your testing when developing your prototype. The Entity API will return test data previously shared by our officer via email. For test data matters, please contact us.

Note:

  • Domain Name: sandbox.api.edh.gov.sg
  • PKI digital signature is not required for all APIs.
  • Refer to EDH TUO Sample for the full url to call for Sandbox Environment

2. Test Environment

The test enviroment is used for testing your application with the full security measures required in production. The Entity API will return test data previously shared by our officer via email. For test data matters, please contact us.

Note:

  • Domain Name: test.api.edh.gov.sg
  • PKI digital signature is required for Entity APIs.
    Refer to Security > Request Signing for the steps to sign your request.

3. Production Environment

The production enviroment is the actual live environment with full security measures and live data.

Note:

  • Domain Name: api.edh.gov.sg
  • PKI digital signature is required for Entity APIs.
    Refer to Security > Request Signing for the steps to sign your request.

Scheduled Downtimes

The following are the scheduled downtimes for the various environments:

Production Environment

  • Once a month, Sunday 12:00 am to 8:00 am (date to be advised)

Security

HTTPS Interface

EDH's API gateway supports accessing of APIs via the following interfaces:

  • HTTP version 1.1 connection over TLS (Transport Layer Security) version 1.1 or 1.2 standards, and ciphersuites:

    • using AES (Advanced Encryption Standard) and SHA (Secure Hash Algorithm),
    • on either GCM (Galois/Counter Mode) or CBC (Cipher Block Chaining) mode.
  • Below is the list of recommended cipher suites that you may use:

    • TLS_RSA_WITH_AES_256_GCM_SHA384
    • TLS_RSA_WITH_AES_128_GCM_SHA256
    • TLS_RSA_WITH_AES_256_CBC_SHA256
    • TLS_RSA_WITH_AES_256_CBC_SHA
    • TLS_RSA_WITH_AES_128_CBC_SHA256
    • TLS_RSA_WITH_AES_128_CBC_SHA

IMPORTANT: ensure your server supports TLS 1.1 or 1.2 and supports a cipher suite in the list above.

Accessing the RESTful API using prior versions of TLS or unsupported ciphersuites will result in connectivity errors. EDH's API gateway does not support 2-way TLS client nor mutual authentication.

API HTTP interface features:

  1. JSON (JavaScript Object Notation) is the supported data media format and indicated in Content-Type header application/json, also
  2. Content-Length header is omitted by having Transfer-Encoding header chunked emitted for streaming data, and
  3. GZip (GNU Zip) response compression is supported by opt-in Accept-Encoding: gzip and indicated in Content-Encoding header gzip.

Application Authentication

Access to all server-to-server APIs will be authenticated by EDH's API gateway. Prior to consumption of API, respective consumers are required to have:

  • approval of access, onboarding process for the required API resources will be provisioned, and
  • authentication credentials are then supplied and exchanged.

Authentication methods provided by EDH's API gateway on internet:

  • Digital signature should be produced using a RSA private key with corresponding public certificate issued by one of the following compatible CAs:
    • digiCert
    • Entrust
    • Comodo/Sectigo
    • VeriSign
    • GlobalSign
    • GeoTrust
    • Thawte

Request Signing

NOTE: Test and Production Environments only

All server-to-server API requests are to be digitally signed, by including the following parameters and values in the Authorization header:

PKI_SIGN app_id="{app_id}",
nonce="{random_nonce}",
signature_method="RS256",
signature="{base64_url_percent_encoded_signature}",
timestamp="{unix_epoch_in_milliseconds}"

Note: Above sample is separated by lines for ease-of-reading, and new-line denotations are to be omitted in the actual request.

  • {app_id} is the APP ID credential supplied upon onboarding,

  • {random_nonce} is an unique randomly generated text used for replay prevention,

  • {signature_algorithm} is the signature algorithm of the authenticating gateway.

    • Value of signature_algorithm = RS256
  • {base64_url_percent_encoded_signature} is the binary of the generated signature encoded in Base64 URL-safe format,

  • {unix_epoch_in_milliseconds} is the UNIX epoch time in milliseconds

Sample header with authorization parameters

Below is an example of an Authorization header for the sample application. Make sure you list the parameters in the sequence shown below.

  Authorization: PKI_SIGN
  app_id="STG2-MYINFO-SELF-TEST",
  nonce="150590021034800",
  signature_method="RS256",
  signature="EEm+HEcNQajb5FkVd82zjojk+daYZXxSGPCOR2GHZeoyjZY1PK+aFMzHfWu7eJZYMa5WaEwWxdOdq5hjNbl8kHD7bMaOks7FgEPdjE++TNomfv7SMktDnIvZmPYAxhjb/C9POU2KT6tSlZT/Si/qMgD1cryaPwSeMoM59UZa1GzYmqlkveba7rma58uGwb3wZFH0n57UnouR6LYXDOOLkqi8uMZBuvRUvSJRXETAj2N0hT+4QJiN96Ct6IEQh/woZh0o74K5Ol9PpDSM08qC7Lj6N/k694J+hbBQVVviGn7/6mDkfbwdMDuoKs4t7NpqmAnwT+xaQSIZcexfrAVQYA==",
  timestamp="1505900210349"

Sample Code in NodeJS

  // generates the security headers for calling API gateway
  function generateAuthorizationHeader(url, params, method, strContentType, authType, appId, keyCertContent, passphrase) {

    if (authType == "L2") {
      return generateRS256Header(url, params, method, strContentType, appId, keyCertContent, passphrase);
    } else {
      return "";
    }
  };

  // Signing Your Requests
  function generateRS256Header(url, params, method, strContentType, appId, keyCertContent, keyCertPassphrase) {
    var nonceValue = nonce();
    var timestamp = (new Date).getTime();

    // A) Construct the Authorisation Token Parameters
    var defaultAuthHeaders = {
      "app_id": appId, // App ID assigned to your application
      "nonce": nonceValue, // secure random number
      "signature_method": "RS256",
      "timestamp": timestamp // Unix epoch time
    };

    // B) Forming the Base String
    // Base String is a representation of the entire request (ensures message integrity)

    // i) Normalize request parameters
    var baseParams = sortJSON(_.merge(defaultAuthHeaders, params));

    var baseParamsStr = qs.stringify(baseParams);
    baseParamsStr = qs.unescape(baseParamsStr); // url safe

    // ii) concatenate request elements (HTTP method + url + base string parameters)
    var baseString = method.toUpperCase() + "&" + url + "&" + baseParamsStr;

    // C) Signing Base String to get Digital Signature
    var signWith = {
      key: fs.readFileSync(keyCertContent, 'utf8')
    }; // Provides private key

    // Load pem file containing the x509 cert & private key & sign the base string with it to produce the Digital Signature
    var signature = crypto.createSign('RSA-SHA256')
      .update(baseString)
      .sign(signWith, 'base64');

    // D) Assembling the Authorization Header
    var strAuthHeader = "PKI_SIGN app_id=\"" + appId + // Defaults to 1st part of incoming request hostname
      "\",nonce=\"" + nonceValue +
      "\",signature_method=\"RS256\"" +
      ",signature=\"" + signature +
      "\",timestamp=\"" + timestamp +
      "\"";

    return strAuthHeader;
  };

Payload Signing and Encryption (Entity)

NOTE: Entity APIs in Test and Production environments only

The response payload for the Entity API (for test and production environments) is first signed, then encrypted:

Encryption protects the data at rest while a signed payload means, if necessary, you will be able to pass this signed payload to a 3rd party where they can verify the payload's integrity with our public certificate.

In order to read the payload, you have to perform the following steps in order:

  1. Decrypt the payload with your application's private key.
  2. Validate the decrypted payload signature with our public key.
  3. Decode the verified JWS payload using Base64 decode.

After doing the above steps, your application will be able to extract the payload in JSON format.

STEP 1: Decryption

  • Encryption is done using your application's public key that you provided during onboarding. Decryption of the payload should be using the private key of that key-pair.
  • Current encryption algorithms used:
    • RSA-OAEP (for content key wrapping)
    • AES256GCM (for content encrytion)

Sample Code in NodeJS

  // Sample Code for decrypting JWE
  // Decrypt JWE using private key
  function decryptJWE(header, encryptedKey, iv, cipherText, tag, privateKey) {

    return new Promise((resolve, reject) => {

      var keystore = jose.JWK.createKeyStore();

      var data = {
        "type": "compact",
        "ciphertext": cipherText,
        "protected": header,
        "encrypted_key": encryptedKey,
        "tag": tag,
        "iv": iv,
        "header": JSON.parse(jose.util.base64url.decode(header).toString())
      };
      keystore.add(fs.readFileSync(privateKey, 'utf8'), "pem")
        .then(function(jweKey) {
          // {result} is a jose.JWK.Key
          jose.JWE.createDecrypt(jweKey)
            .decrypt(data)
            .then(function(result) {
              resolve(JSON.parse(result.payload.toString()));
            })
            .catch(function(error) {
              reject(error);
            });
        });

    })
    .catch (error => {
      throw "Error with decrypting JWE";
    })
  }

STEP 2: Verification of Signature

The decrypted payload is signed according to JWS (JSON Web Signature) format, similar to the access token.

  • signature algorithm used is RS256.

Sample Code in NodeJS

  // Sample Code for Verifying & Decoding JWS or JWT
  function verifyJWS(jws, publicCert) {
    // verify payload
    // ignore notbefore check because it gives errors sometimes if the call is too fast.
    try {
      var decoded = jwt.verify(jws, fs.readFileSync(publicCert, 'utf8'), {
        algorithms: ['RS256'],
        ignoreNotBefore: true
      });
      return decoded;
    }
    catch(error) {
      throw("Error with verifying and decoding JWS");
    }
  }

Understanding the Data Structure (NEW)

EDH Entity data follows a specific structure that you need to understand to traverse the data effectively. This section will explain the structure in detail.

The diagram below illustrates how the data is represented logically:
EDH Entity Data Structure

Data Items (Top-Level)

Data Items are attributes that can be requested in the API. Each top-level data item can either be a data item object or an array of data item objects. Each data item object will consist of the following properties:

  • source (see below)
  • unavailable (in certain situations - see below)
  • additional data properties containing data values or arrays

Data Source

The source property indicates the source of data. Possible values are:

  • '1' - Government-verified
  • '3' - Field is Not Applicable to this Entity

Data Properties

In each data item, there can be multiple data properties or arrays of data properties.

Each data property will contain either:

  • a value property, or
  • a pair of code and desc properties, or
  • an array of data properties, or
  • other data properties

Note:

  • value property can be strings, numbers, or dates.
  • code and desc pairs will contain the code and its matching description.
  • value is mutually exclusive from (code + desc); i.e. if there is a value, there will not be any code or desc.
  • Where there is code, there will always be a desc - no value will be present.

Exceptions: For these cases, the values will be directly in the property and not in a value, code or desc subproperty:

  • for data item metadata properties; e.g. source and unavailable
  • for discriminator properties; e.g. type in address formats

Data Not Applicable

Sometimes, a requested data item or data property is not applicable to the entity. Examples include:

  • a Business Entity (entitytype = BN) will never have a shareholders data item.
  • a Business Entity (entitytype = BN) will never have a declarations data item.
  • a Local Company (entitytype = LC) will never have commencment-date data property.

For a full list, refer to the descriptions in each of the data properties of the entity data model.

Data Item Not Applicable

When a requested data item is not applicable to the entity:

  • for data item objects, the source property will be 3
  • for data item arrays, an empty array will be returned

In such cases, please ignore the data item completely. Check out the different Entity schemas for each type by selecting the different entitype discriminator in the specifications. E.g. if you choose "BN" (Business) entity type, you will see that shareholders schema is an empty array.

Data Property Not Applicable

  • The Entity object has a entitytype discriminator which helps to specify the data properties applicable to each entity type.
  • When a data property is not applicable to the entity, it will not appear in the schema of that particular entity type.

Data Unavailable

In other situations, a requested data item might not have any data for that data item from the data source; i.e. data is unavailable. Examples include:

  • when an entity does not have any grants submitted/approved

Data Item Unavailable

  • for data item objects, the data item will have the property unavailable with value true.
    In such cases, no additional properties (other than source) will be provided for the data item.
  • for data item arrays, an empty array will be returned.

Please display as "Not Available" in your form.

Data Property Unavailable

  • for data property objects, the value or code/desc will be empty value ("") or NaN.
  • for arrays of data properties, an empty array will be returned.

Error Handling

The RESTful API(s) uses HTTP specification standard status codes to indicate the success or failure of each request. Except gateway errors, the response content will be in the following JSON format:

{
    "code": "integer (int32)",
    "message": "string"
}

Refer to the individual API definitions for the error codes you might encounter for each API.

Support

Please refer to the links below for the following supporting materials where relevant:

For queries, please submit a request at partnersupport.corppass.gov.sg

EDH TUO

Entity API resource operations to access corporate entity details.

Entity

This API returns entity data from EDH.

Note: Null value indicates that an attribute is unavailable.

path Parameters
uen
required
string <= 40 characters
Example: T15LP0010D

Required URL path parameter of the entity's unique entity number (UEN).

query Parameters
txnNo
string

Transaction ID from requesting digital services for cross referencing.

attributes
required
Array of strings
Example: attributes=basic-profile, previous-names, previous-uens, financials, shareholders

Comma separated list of attributes requested. Possible attributes are:

  • basic-profile: Basic Entity Profile (from ACRA)
  • addresses: Addresses (from ACRA)
  • history: History (from ACRA)
  • financials: Financials (from ACRA)
  • capitals: Capitals (from ACRA)
  • declarations: Declarations (from ACRA)
  • charges: Charges (from ACRA)
  • shareholders: Shareholders (from ACRA)
  • shareholders-list: Shareholders List (from ACRA)
  • subsidiaries-list: Subsidiaries List (from ACRA)
  • appointments: Appointments (from ACRA)
  • licences: Licences (from GoBusiness)
  • grants: Grants (from BGP)
  • corppass: CorpPass Accounts (from CorpPass)
  • builders: Builders Information (from BCA)
  • contractors: Contractors Information (from BCA)
client_id
required
string
Example: client_id=STG-180099999K-TEST01

Unique ID for your application.

header Parameters
Authorization
required
string

Add authorization token constructed containing the RSA digital signature of the base string. Refer to Security > Request Signing on how this token should be generated.

Note: Not required when calling Sandbox API.

Responses

Request samples

// function to prepare request for Entity API
function createEntityRequest(uen) {
  var url = _entityApiUrl + "/" + uen + "/";
  var cacheCtl = "no-cache";
  var method = "GET";
  var request = null;
  // assemble params for Entity API
  var strParams = "client_id=" + _clientId +
    "&attributes=" + _attributes;
  var params = querystring.parse(strParams);

  // assemble headers for Entity API
  var strHeaders = "Cache-Control=" + cacheCtl;
  var headers = querystring.parse(strHeaders);
  var authHeaders;

  // Sign request and add Authorization Headers
  authHeaders = generateAuthorizationHeader(
    url,
    params,
    method,
    "", // no content type needed for GET
    _authLevel,
    _clientId,
    _privateKeyContent
  );

  if (!_.isEmpty(authHeaders)) {
    _.set(headers, "Authorization", authHeaders);
  }

  // invoke token API
  var request = restClient.get(url);

  // Set headers
  if (!_.isUndefined(headers) && !_.isEmpty(headers))
    request.set(headers);

  // Set Params
  if (!_.isUndefined(params) && !_.isEmpty(params))
    request.query(params);

  return request;
}

Response samples

Content type
application/json
Example
{
  • "grants": [
    ],
  • "financials": [ ],
  • "addresses": [
    ],
  • "appointments": [
    ],
  • "builders": [
    ],
  • "basic-profile": {
    },
  • "shareholders": [ ],
  • "capitals": [ ],
  • "history": {
    },
  • "declarations": {
    },
  • "contractors": [
    ],
  • "charges": [ ],
  • "corppass": [
    ],
  • "entitytype": "BN",
  • "licences": [
    ]
}

EDH TUO Sample

Entity API resource operations to access corporate entity details. (Sandbox)

Entity

This API returns entity data from EDH.

Note: Null value indicates that an attribute is unavailable.

path Parameters
uen
required
string <= 40 characters
Example: T15LP0010D

Required URL path parameter of the entity's unique entity number (UEN).

query Parameters
attributes
required
Array of strings
Example: attributes=basic-profile, previous-names, previous-uens, financials, shareholders

Comma separated list of attributes requested. Possible attributes are:

  • basic-profile: Basic Entity Profile (from ACRA)
  • addresses: Addresses (from ACRA)
  • history: History (from ACRA)
  • financials: Financials (from ACRA)
  • capitals: Capitals (from ACRA)
  • declarations: Declarations (from ACRA)
  • charges: Charges (from ACRA)
  • shareholders: Shareholders (from ACRA)
  • shareholders-list: Shareholders List (from ACRA)
  • subsidiaries-list: Subsidiaries List (from ACRA)
  • appointments: Appointments (from ACRA)
  • licences: Licences (from GoBusiness)
  • grants: Grants (from BGP)
  • corppass: CorpPass Accounts (from CorpPass)
  • builders: Builders Information (from BCA)
  • contractors: Contractors Information (from BCA)

Responses

Response samples

Content type
application/json
Example
{
  • "grants": [
    ],
  • "financials": [ ],
  • "addresses": [
    ],
  • "appointments": [
    ],
  • "builders": [
    ],
  • "basic-profile": {
    },
  • "shareholders": [ ],
  • "capitals": [ ],
  • "history": {
    },
  • "declarations": {
    },
  • "contractors": [
    ],
  • "charges": [ ],
  • "corppass": [
    ],
  • "entitytype": "BN",
  • "licences": [
    ]
}