Xink API Reference


Version: 1.4

Date: Jan 23, 2025

Table of Contents

Overview

Xink provides REST API for external clients. All traffic between a client application and Xink service is transported by encrypted HTTP requests and responses.

Step 1. Authentication/Authorization

We use OAuth2 to control access to Xink APIs, external clients should use ClientCredentialsGrant in particular. Client should request access token from Xink authorization server, then use the token in all subsequent requests to the API.

In Xink admin portal you need to create an API user. Navigate to preferences->admins and add an API user. Give the user proper permissions and a good password. The user referred to in this documentation is an API user.

Authorization server URI: https://auth.xink.io
Authorization endpoint: /OAuth/Authorize
Token endpoint: /OAuth/Token

Step 2. Discovery

We offer five data centers. First you should discover data center (APIRoot) belonging to your account. You make a GET request to get necessary details for your endpoint.

Discovery endpoint: https://auth.xink.io/Discovery

Example of a result for EU data center:

{
    "Success": true,
    "DataCenterID": "EU",
    "APIRoot": "https://e-eu.xink.io",
    "SyncRoot": "https://s-eu.xink.io",
    "ImgRoot": "https://i-eu.xink.io",
    "TrackingRoot": "https://t-eu.xink.io"
}

Step 3. Request to an APIRoot

Use API root you received from discovery step to make an API call for your method. Below we continue an example for EU.

API ROOT: e-eu.xink.io/{api/1.0/...}

Please note scope names employeeread and employeesignaturesread are required to get employee list and signatures. Each operation may require some scope.
By default token is valid for 2 hours since authorization request. On later stages, this value might be changed to 10-15 minutes.

Summary of All Available API Controllers

Account

[HttpGet,  Route("api/1.0/account/info")]

Employee

[HttpGet,  Route("api/1.0/employee/list/{offset:int=0}/{limit:int=500}")]
[HttpGet,  Route("api/1.0/employee/{email}/fields")]
[HttpGet,  Route("api/1.0/employee/{email}/signatures")]
[HttpPost, Route("api/1.0/employee/upload")]
[HttpPost, Route("api/1.0/employee/delete")]

Image

[HttpPost,   Route("api/1.0/image")]
[HttpGet,    Route("api/1.0/image/list/{offset:int=0}/{limit:int=500}")]

Signature

[HttpGet,    Route("api/1.0/signature/list/{offset:int=0}/{limit:int=500}")]
[HttpPost,   Route("api/1.0/signature/")]
[HttpPost,   Route("api/1.0/signature/{id}/update")]
[HttpDelete, Route("api/1.0/signature/{id}")]
[HttpPost, Route("api/1.0/signature/{id}/delete")]

Signature Import

[HttpPost, Route("api/1.0/signatureimport/{id}/image")]
[HttpPost, Route("api/1.0/signatureimport/{id}")]

Rerouting

[HttpGet,  Route("api/1.0/rerouting/status")]
[HttpPost, Route("api/1.0/rerouting/clearmap")]
[HttpPost, Route("api/1.0/rerouting/replacemap")]

Managed Accounts

[HttpGet,  Route("api/1.0/managedAccounts/list")]

Shared Mailboxes

[HttpPost, Route("api/1.0/employees/{email}/sharesSignatureWith/{emailSharedWith}")]
[HttpDelete, Route("api/1.0/employees/{email}/sharesSignatureWith/{emailSharedWith}")]
[HttpGet, Route("api/1.0/employees/{email}/shared")]

Examples of API Controller’s Request-Response

Scopes

employeeread
employeefieldsread
employeectrl (WRITE)
employeesignaturesread
signaturectrl (WRITE)
managedaccountsread

Account

[HttpGet,  Route("api/1.0/account/info")]

Scope: employeeread

{
    "CompanyName": "Some Company",
    "LicensedEdition": "Xink Campaign",
    "LicensedCount": 6,
    "CreatedDate": "2013-02-07T07:37:52.78",
    "RenewalDate": null,
    "InvoiceEmail": "[email protected]",
    "TotalEmployees": 530,
    "Signatures": 32,
    "DefaultSignature": null,
    "ReplySignature": null,
    "RunningCampaigns": [
        {
            "Name": "disclaimer2",
            "ContentText": null,
            "ContentHTML": "disclaimer2",
            "Active": true,
            "TrackClicks": true,
            "Weight": 2,
            "Notes": null,
            "EffectiveActive": true,
            "SignaturesCount": 0,
            "ClickCount": 0,
            "ViewCount": 8
        },
        ...
        {
            "Name": "Subscribe",
            "ContentText": null,
            "ContentHTML": "\"\"",
            "Active": true,
            "TrackClicks": true,
            "Weight": 1,
            "Notes": null,
            "EffectiveActive": true,
            "SignaturesCount": 1,
            "ClickCount": 11,
            "ViewCount": 15
        }
    ],
    "UpcomingCampaigns": [],
    "TopCampaigns": [],
    "DisabledCampaigns": [
        {
            "Name": "__custom_tracking_link_01",
            "ContentText": null,
            "ContentHTML": null,
            "Active": false,
            "TrackClicks": true,
            "Weight": 1,
            "Notes": null,
            "EffectiveActive": false,
            "SignaturesCount": 1,
            "ClickCount": 0,
            "ViewCount": 53
        },
        ...
        {
            "Name": "new campaign",
            "ContentText": null,
            "ContentHTML": null,
            "Active": false,
            "TrackClicks": true,
            "Weight": 1,
            "Notes": null,
            "EffectiveActive": false,
            "SignaturesCount": 0,
            "ClickCount": 0,
            "ViewCount": 0
        }
    ],
    "DateFrom": "2023-07-09T00:00:00+00:00"
}

Employee

[HttpGet,  Route("api/1.0/employee/list/{offset:int=0}/{limit:int=500}")]

Example: /api/1.0/employee/list/0/3

Response contains Offset and Limit parameters values used in the request (or defaults if no parameters were supplied); and actual array of Items, each represents one employee.

Scope: employeeread

{
    "Limit": 500,
    "Offset": 0,
    "SearchQuery": null,
    "Items": [
        {
            "Email": "[email protected]",
            "FirstName": "John",
            "LastName": "Doe",
            "DisplayName": "Jonny D"
        },
        {
            "Email": "[email protected]",
            "FirstName": "Maria",
            "LastName": "Doe",
            "DisplayName": "Maria D"
        },
        ...
    ]
}
[HttpGet,  Route("api/1.0/employee/{email}/fields")]

Scope: employeefieldsread

{
    "Fields": [
        {
            "Code": "Country",
            "DisplayName": "Country",
            "FieldValue": null,
            "IsImage": false
        },
        {
            "Code": "DisplayName",
            "DisplayName": "Display Name",
            "FieldValue": "somename",
            "IsImage": false
        },
        ...
        {
            "Code": "LastName",
            "DisplayName": "Last Name",
            "FieldValue": "somename",
            "IsImage": false
        },
        {
            "Code": "Email",
            "DisplayName": "Employee's Email",
            "FieldValue": "[email protected]",
            "IsImage": false
        },
        ...
    ]
}
[HttpGet,  Route("api/1.0/employee/{email}/signatures")]

Scope: employeesignaturesread

{
    "Clean": false,
    "SetDefault": true,
    "SetReply": false,
    "Signatures": [
        {
            "Name": "",
            "HTML": null,
            "Text": null,
            "DefaultNew": false,
            "DefaultReply": true
        },
        {
            "Name": "(KM) 3-4-Sterne Offerte",
            "HTML": "

\"\"

  • Clean flag represents value of “Delete all existing email signatures in Outlook” preference.
  • Signature supposed to be downloaded directly into “Signatures” folder of Outlook user profile. Each signature must be saved into a file named exactly as field Name value with .html extension added.
[HttpPost, Route("api/1.0/employee/upload")]

Scope: employeectrl

Request:

{
    "Items": [
        {
            "Email":"[email protected]",
            "FirstName":"John",
            "LastName":"Doe",
            "DisplayName":"John Doe",
            "Fields": [
                {
                    "Code":"City",
                    "FieldValue":"New York"
                },
                {
                    "Code":"Country",
                    "FieldValue":"USA"
                }
            ]
        },
        {
            "Email":"[email protected]",
            "FirstName":"Peter",
            "LastName":"Johnson",
            "DisplayName":"",
            "Fields": [
                {
                    "Code":"Department",
                    "FieldValue":"Sales"
                },
                {
                    "Code":"Facebook",
                    "FieldValue":""
                }
            ]
        }
    ]
}

Response:

{
    "Items": [
        "[email protected]: OK",
        "[email protected]: OK"
    ]
}
[HttpPost, Route("api/1.0/employee/delete")]

Scope: employeectrl

Request:

{
    "Items": [
        {
            "Email":"[email protected]"
        },
        {
            "Email":"[email protected]"
        }
    ]
}

Response: None

Image

Signature may contain images, like company logo, employee avatar or whatever else. Xink stores those images and performs several actions to prepare Outlook application to use them properly.

Field Name provides exact file name for corresponding image. Images supposed to be saved in the same directory as signatures. It is important; signature HTML refers images just by file name.

Xink server is responsible for making image names unique. If in any case image names are repeated, it is guaranteed that these are references to the same image.

There is no dedicated authorization scope for image access. It is enough to provide a token generated for valid client account.

[HttpPost,   Route("api/1.0/image")]

Content-Type: multipart/form-data

Key: file

Value: someImg.png

Response:

{
    "AccountUniqueName": "BT4",
    "ImageUniqueName": "i",
    "RelativeImageUrl": "https://i.xink.io/Images/Get/BT4/i.png",
    "Name": "img21.png",
    "DateCreated": "2023-10-10T09:18:18.21",
    "MD5": "3A16278045564DAEIUB5A52B23C8B",
    "SHA1": "A327FCE8098NIJN1E39D2683616DE71CBA4"
}
[HttpGet,    Route("api/1.0/image/list/{offset:int=0}/{limit:int=500}")]

Scope: signaturectrl

{
    "Limit": 500,
    "Offset": 0,
    "Items": [
        {
            "AccountUniqueName": "B4",
            "ImageUniqueName": "i6",
            "RelativeImageUrl": "https://i.xink.io/Images/Get/B4/i6.png",
            "Name": "image001.png",
            "DateCreated": "2014-06-18T11:59:38.843",
            "MD5": "255F0174C3EOKN230283222FEE",
            "SHA1": "89E5C303A9D90283NEED815735FF2C5239871"
        },
        {
            "AccountUniqueName": "B3",
            "ImageUniqueName": "i1",
            "RelativeImageUrl": "https://i.xink.io/Images/Get/B3/i1.png",
            "Name": "image002.png",
            "DateCreated": "2014-06-18T12:19:18.76",
            "MD5": "51BCBB0923NJEB223A2BA122E0",
            "SHA1": "FC4907WOEINR0293712AF8BF8D9C727D15"
        },
        ...
    ]
}

Signature

[HttpGet,    Route("api/1.0/signature/list/{offset:int=0}/{limit:int=500}")]

Scope: signaturectrl

{
    "Limit": 500,
    "Offset": 0,
    "Items": [
        {
            "SignatureID": "372236",
            "Name": "eMailSignature",
            "ContentText": "((FirstName)) ((LastName))\r\n((JobTitle))\r\n\r\n((Company))\r\n((Department))\r\nEmail: ((Email))\r\nPhone: ((DirectPhone))\r\n((WebSite))",
            "ContentHTML": "
\r\n((FirstName)) ((LastName))
\r\n((JobTitle))\r\n

\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n\t\r\n
 
\r\n", "DefaultNew": false, "DefaultReply": false, "Available": false, "Public": false, "Notes": null }, ... ] }
[HttpPost,   Route("api/1.0/signature/")]

Name (string, required): The name of the signature.

ContentText (string, required): The text content of the signature.

ContentHTML (string, required): The HTML content of the signature.

Notes (string, optional): Optional notes or additional information about the signature.

Request:

{
    "Name": "MySignature",
    "ContentText": "Hello, this is my signature text.",
    "ContentHTML": "

Hello, this is my HTML signature.

", "Notes": "Optional notes about the signature" }

Response:

{
    "SignatureID": "12345"
}
[HttpPost,   Route("api/1.0/signature/{id}/update")]

Scope: signaturectrl

Request:

{
    "Name": "MySignature-UPDATED",
    "ContentText": "Hello, this is my signature text UPDATED.",
    "ContentHTML": "

Hello, this is my HTML signature UPDATED.

", "Notes": "Optional notes about the signature UPDATED" }

Response:

{
    "SignatureID": "12345"
}
[HttpDelete, Route("api/1.0/signature/{id}")]
[HttpPost, Route("api/1.0/signature/{id}/delete")]

Signature Import

[HttpPost, Route("api/1.0/signatureimport/{id}/image")]
[HttpPost, Route("api/1.0/signatureimport/{id}")]

Rerouting

[HttpGet,  Route("api/1.0/rerouting/status")]
{
    "StatusCode": 0,
    "Domains": [],
    "IsSMTPCacheReady": true
}
[HttpPost, Route("api/1.0/rerouting/clearmap")]
[HttpPost, Route("api/1.0/rerouting/replacemap")]

Managed Accounts

[HttpGet,  Route("/api/1.0/managedAccounts/list")]

Scope: managedaccountsread

{
    "Items": [
        {
            "id": 26845,
            "name": "admin1",
            "email": "[email protected]",
            "employees": 1,
            "licenses": 0,
            "version": "Brand",
            "using": 0,
            "note": "4",
            "folders": [],
            "createdDate": "2019-02-22T08:45:29.36",
            "endDate": null
        },
        {
            "id": 28760,
            "name": "[email protected]",
            "email": "[email protected]",
            "employees": 1,
            "licenses": 0,
            "version": "Brand",
            "using": 0,
            "note": "111221",
            "folders": [
                "1"
            ],
            "createdDate": "2019-04-24T15:22:24.157",
            "endDate": "2019-05-08T00:00:00"
        },
        {
            "id": 30598,
            "name": "admin3",
            "email": "[email protected]",
            "employees": 1,
            "licenses": 0,
            "version": "Brand",
            "using": 0,
            "note": "2",
            "folders": [
                "1",
                "2"
            ],
            "createdDate": "2019-06-18T06:58:56.243",
            "endDate": null
        }
    ]
}

Shared Mailboxes

[HttpPost, Route("api/1.0/employees/{email}/sharesSignatureWith/{emailSharedWith}")]

Scope: employeectrl

Adds shared employee. The employee {emailSharedWith} can use the signatures of the employee {email}

[HttpDelete, Route("api/1.0/employees/{email}/sharesSignatureWith/{emailSharedWith}")]

Scope: employeectrl

Deletes shared employee.

[HttpGet, Route("api/1.0/employees/{email}/shared")]

Scope: employeectrl

Returns a list of shared employees whose signatures can be used by employee {email}

{
    "Email": "[email protected]",
    "SharedEmployees": [
        {
            "Email": "[email protected]",
            "DisplayName": "Sam Doe"
        }
    ]
}

Did you find it helpful? Yes No

Send feedback
Sorry we couldn't be helpful. Help us improve this article with your feedback.
Quick 1-on-1 Demo | Ⓒ 2025 Xink