ACES Service API Docs
The ACES Service API Specification defines the API interface for ACES Services to be listed on the Service Marketplace. SDKs are available in Java, Go, PHP, JavaScript, Python, and C#.
The Service API provides a common way for to define blockchain interoperability services and exposes them over a simple REST-ful API. The API allows service consumers to create Service contracts, pay for contracts, get results of contract executions.
Overview
Get Service Info:
curl 'https://bitcoin-transfer-service.example.com/info' \
-X GET
AcesServiceClient client = new AcesServiceClient(
"https://bitcoin-transfer-service.example.com"
);
Info info = client.getInfo();
{
"name": "BTC to ARK Channel Service",
"description": "Transfer value from BTC to ARK.",
"instructions": "Enter your BTC address to create an BTC to ARK transfer channel.",
"capacities": [
{
"value": 10000,
"unit": "ARK",
"displayValue": "10000.00 ARK"
}
],
"flatFee": "0 BTC",
"percentFee": "1%",
"inputSchema": {
"type": "object",
"properties": {
"recipientArkAddress": {
"type": "string"
}
},
"required": [
"recipientArkAddress"
]
},
"outputSchema": {
"type": "object",
"properties": {
"depositBtcAddress": {
"type": "string"
},
"recipientArkAddress": {
"type": "string"
},
"transfers": {
"type": "array",
"properties": {
"btcAmount": {
"type": "string"
},
"btcToArkRate": {
"type": "string"
},
"btcFlatFee": {
"type": "string"
},
"btcPercentFee": {
"type": "string"
},
"btcTotalFee": {
"type": "string"
},
"arkSendAmount": {
"type": "string"
},
"arkTransactionId": {
"type": "string"
},
"createdAt": {
"type": "string"
}
}
}
}
}
}
Create Service Contract:
curl 'http:/btc-ark-channel-service.example.com/contracts' \
-X POST \
-d '{
"correlationId": "8bbcbe9c-4955-4fd6-b97b-0bf3e8b5809f",
"arguments": {
"recipientArkAddress": "ARNJJruY6RcuYCXcwWsu4bx9kyZtntqeA"
}"
}'
AcesServiceClient client = new AcesServiceClient(
"https://bitcoin-transfer-service.example.com"
);
Map<String, Object> arguments = new HashMap();
arguments.put("recipientArkAddress", "ARNJJruY6RcuYCXcwWsu4bx9kyZtntqeAx");
ContractRequest request = new ContractRequest();
request.setCorrelationId(UUID.randomUUID());
request.setArguments(arguments);
Contract contract = client.createContract(request);
{
"id" : "abe05cd7-40c2-4fb0-a4a7-8d2f76e74978",
"correlationId" : "8bbcbe9c-4955-4fd6-b97b-0bf3e8b5809f",
"createdAt":"2017-07-01T22:35:57.695Z",
"status": "executed",
"results": {
"depositBtcAddress": "1F1tAaz5x1HUXrCNLbtMDqcw6o5GNn4xqX",
"recipientArkAddress": "ARNJJruY6RcuYCXcwWsu4bx9kyZtntqeAx",
"transfers": [
{
"createdAt": "2017-07-01T22:36:57.005Z",
"btcAmount": "1.000",
"btcToArkRate": "0.040",
"btcFlatFee": "0",
"btcPercentFee": "1",
"btcTotalFee": "0.001",
"arkSendAmount": "40.000",
"arkTransactionId": "49f55381c5c3c70f96d848df53ab7f9ae9881dbb8eb43e8f91f642018bf1258f"
}
]
}
}
Get Service Contract:
curl 'http://bitcoin-transfer-service.example.com/contracts/abe05cd7-40c2-4fb0-a4a7-8d2f76e74978' \
-X GET
AcesServiceClient client = new AcesServiceClient(
"https://bitcoin-transfer-service.example.com"
);
Contract contract = client.getContract("abe05cd7-40c2-4fb0-a4a7-8d2f76e74978");
{
"id" : "abe05cd7-40c2-4fb0-a4a7-8d2f76e74978",
"correlationId" : "8bbcbe9c-4955-4fd6-b97b-0bf3e8b5809f",
"createdAt":"2017-07-01T22:35:57.695Z",
"status": "executed",
"results": {
"depositBtcAddress": "1F1tAaz5x1HUXrCNLbtMDqcw6o5GNn4xqX",
"recipientArkAddress": "ARNJJruY6RcuYCXcwWsu4bx9kyZtntqeAx",
"transfers": [
{
"createdAt": "2017-07-01T22:36:57.005Z",
"btcAmount": "1.000",
"btcToArkRate": "0.040",
"btcFlatFee": "0",
"btcPercentFee": "1",
"btcTotalFee": "0.001",
"arkSendAmount": "40.000",
"arkTransactionId": "49f55381c5c3c70f96d848df53ab7f9ae9881dbb8eb43e8f91f642018bf1258f"
}
]
}
}
At the center of the ACES Service API is the Service Contract. Each service defines and operates on one type of contract. A Service Contract defines a particular service a provider is able to fulfil, which can be anything from uploading a file to a storage blockchain, performing value transfers, creating smart contracts, executing code on blockchain based computing platforms, or interacting with IoT hardware.
Consumers of a service get the contract schema from in the Service Info endpoint. This tells you what parameters a contract takes and what data is returned from the contract. ACES uses the Json Schema format for defining data schemas. ACES Services may implement any number of Contract Interfaces, which semantically define a set of contract arguments and result properties.
ACES Services can react in real-time to blockchain events by registering with an
Encoded Listener instance.
For example, an ACES Service can register with an Ark Encoded Listener and
accept service contract payment via an Ark transaction by listening for specific
SmartBridge
data associated with the service contract. Services can also create
wallets for a service contract and listen for deposit transactions into that wallet.
Contract Interfaces
The ACES Service API defines a highly abstract blueprint for services that can perform many different types of functions across many different blockchains. As such, ACES contracts are able to accept a flexible range of input values and return an equally flexible range of result data for contract executions.
To simplify integration of services into a common Marketplace, the ACES Service API defines several Contract Interfaces to control presentational aspects of different types of contracts.
These interfaces tell consumers the semantic meaning of certain sets of contract request and response parameters, so they can be rendered or controlled differently in the Marketplace or other UI applications.
We expect to add more Contract Interfaces as more blockchains are integrated
and different types of contracts are defined. Some examples may include interfaces
such as fileUpload
, multiFileUpload
, expirable
, etc...
Ark SmartBridge Payable
The arkSmartbrigePayable
interface specifies that the contract can be paid for
using an Ark SmartBridge transaction.
Response Parameters:
Parameter | Type | Description |
---|---|---|
arkServiceAddress | String | The service Ark address to send payment transaction to. |
Ark Returnable
The arkReturnable
interface specifies that the contract can return refundable
ARK to the given return address.
Request Parameters:
Parameter | Type | Description |
---|---|---|
arkReturnAddress | String | The return Ark address to send refund transaction to. |
Expirable
The expirable
interface specifies that the contract will expire after the given
date if not executed.
Response Parameters:
Parameter | Type | Description |
---|---|---|
expirationDate | String | The ISO 8601 formatted date time string specifying when the contract will expire. |
Authentication
The ACES Service API does not define any authentication method at this time. To secure services, they must be placed behind a reverse proxy that performs basic authentication or other such authorization before allowing requests to the back-end service.
Pagination
url="http://localhost/contracts/3985723987423/executions"
url="$url?pageSize=100"
url="$url&page=4"
url="$url&continuation=839729837520395702375023"
curl -X GET "$url"
ServiceClient client = new ServiceClient("http://localhost");
ContractExecutionsRequest request = new ContractExecutionsRequest();
request.setPageSize(100);
request.setPage(4);
request.setContinuation("933502938509238509283059");
Page<ContractExecution> executionsPage = client.getContractExecutionsPage(request);
{
"pageSize": "100",
"page": "4",
"continuation": "933502938509238509283059",
"items": [
{
"id": "1",
"status": "executed",
"executedAt": "2017-11-01T00:00:00.000Z"
}
]
}
A GET
request that returns a list of unbound items will be paginated
in a way to return only a small number of items per page.
Clients can request additional pages by performing additional GET
requests to retrieve the next page.
Page number is zero-offset such that the first page has page = 0
.
The page response contains a continuation
property that can be added
to GET
requests for the next page to stabilize pagination offsets.
Including the continuation parameter ensures that newly added items
will not shift down items in the next page. This allows pages to be
iterated over without encountering repeat elements as elements are
added.
Errors
ACES Service API instances can return a set of standard HTTP errors classified by the response HTTP Status code.
An request body validation error returns a 400
HTTP Status Code and an error response body
with a detailed description of field validation errors. Consumers should correct the request
before resubmitting the request.
Any 5xx
level errors can be retried without making changes to the request since they
are returned when there is something wrong with the server and not the consumer's request.
Status Codes
ACES Service API instances return errors responses with the following HTTP Status codes:
HTTP Code | Description |
---|---|
400 | The request was invalid. The consumer should read error messages and correct the request body before resending request. |
404 | The requested resource was not found. |
405 | The URL in the request does not support the requested HTTP method. |
429 | Too many requests have been sent over a given time frame and the server has limited the consumer. |
500 | The server had an unexpected error. Consumers should try the request again later. |
503 | The server is running, but not currently accepting traffic. Consumers should try the request again later. |
General Errors
Example error response:
{
"code": "alreadyCancelled",
"message": "The Contract has already been cancelled."
}
Errors always return an error code and human readable error message.
Consumers should handle any expected errors for an API call using the
error code
value.
General Error Codes
Code | Description |
---|---|
notFound | The requested resource was not found. |
invalidRequest | The request body is invalid. See Validation Errors below. |
Validation Errors
Example error request:
curl 'http://localhost/contracts' \
-X POST \
-d '{
"arkAddress": "not-an-addresss"
}'
Example error response:
{
"code": "invalidRequest",
"message": "Request is invalid.",
"fieldErrors": [
{
"field": "arkAddress",
"code": "invalidArkAddress",
"message": "The Ark address given is invalid."
},
{
"field": "arkAmount",
"code": "required",
"message": "Ark amount is required."
}
]
}
Validation errors have http status code = 400
and a response body error code = invalidRequest
.
Any field validation errors are returned in the fieldErrors
list and include the field name corresponding
to the request parameter, validation error code, and human-readable message for the field error.
Field Error Codes
Code | Description |
---|---|
required | The field value is required. |
invalidUrl | The given URL value is invalid. |
tooShort | The field value given is too short. |
tooLong | The field value given is too long. |
Versions
Services instances can upgrade to new backwards compatible versions without breaking client integrations. ACES defines backwards compatible changes as any of the following:
- Adding new API endpoints
- Adding new optional request parameters
- Adding new response properties
- Changing length or format of String properties
If breaking changes to the Service must be made, the provider needs to launch a new version in parallel at a different URL and have clients re-subscribe to the new version URL.
Implementations
The ACES Service API defines a standard protocol to facilitate creation and execution of numerous blockchain interoperability services. As such, it is a high level abstraction of many different service contract types that needs to be implemented and hosted independently. Unlike many conventional business APIs that host their own proprietary services on a single server, ACES Services are designed to be distributed across many servers, where third-party service providers are able to develop, host, monetize, and maintain individual services.
The Service API specifies only the base necessary capabilities for implementing a blockchain interoperability and contracts in a generic way that can support many different use-cases for interoperability services, including those that may utilize multiple different blockchains or interface with physical hardware.
All implementations conforming to the ACES Service API specification can be consumed using the common client libraries and processing logic, allowing different services to easily plugged into applications or listed on the Service Marketplace.
Instances
Instances run on any web server and can be made private or public. Multiple instances may also run on a single web server using different HTTP ports.
We don't make any guarantees on how instances are managed, so consumers will need to host their own instances, subscribe to only trusted providers, or subscribe to multiple instances to ensure they can access services in the case a provider goes down.
The upcoming ACES Service Marketplace will add a layer of trust and stability to Services by verifying service providers and enabling fallbacks in case a provider goes down.
API Reference
Health
Get Health
Get application health information.
Example request:
curl 'http://localhost:8080/status'
ServiceClient client = new ServiceClient("http://localhost");
Health health = client.getHealth();
Returned response:
{
"status": "up"
}
HTTP Request
GET http://localhost:8080/status
Service Info
Get Service Info
Example request:
curl 'http://localhost/info'
ServiceClient client = new ServiceClient("http://localhost");
ServiceInfo serviceInfo = client.getServiceInfo();
Returned response:
{
"name":"ACES",
"description":"an ACES service",
"instructions":"Service usage instructions in markdown format."
"capacities":[1, "BTC", "1.00 BTC"],
"flatFee":"0.01",
"percentageFee":"0.01",
"contractSchema":{},
"interfaces":["arkSmartbridgePayable", "arkReturnable"]
}
Gets Service Info object.
HTTP Request
GET http://localhost/info
Service Contract
Create Service Contract
Example request:
curl 'http://localhost/contracts' \
-X POST \
-d '{
"correlationId": "8bbcbe9c-4955-4fd6-b97b-0bf3e8b5809f",
"arguments": {
"btcAmount": "1.00",
"recipientBitcoinAddress": "1F1tAaz5x1HUXrCNLbtMDqcw6o5GNn4xqX",
"returnArkAddres": "ARNJJruY6RcuYCXcwWsu4bx9kyZtntqeAx"
}
}'
ServiceClient client = new ServiceClient("http://localhost");
Map<String, Object> arguments = new HashMap();
arguments.put("btcAmount", "1.00");
arguments.put("recipientBitcoinAddress", "1F1tAaz5x1HUXrCNLbtMDqcw6o5GNn4xqX");
arguments.put("returnArkAddres", "ARNJJruY6RcuYCXcwWsu4bx9kyZtntqeAx");
ContractRequest request = new ContractRequest();
request.setCorrelationId(UUID.randomUUID());
request.setArguments(arguments);
Contract contract = client.createContract(request);
Returned response:
{
"id" : "f2c0244d-8473-417a-98ce-f30a979e925a",
"correlationId" : "8bbcbe9c-4955-4fd6-b97b-0bf3e8b5809f",
"status": "new",
"btcAmount": "1.00",
"requiredArkAmount" : "2250.00",
"serviceArkAddress": "AewU1vEmPrtQNjdVo33cX84bfovY3jNAkV",
"returnArkAddress" : "ARNJJruY6RcuYCXcwWsu4bx9kyZtntqeAx",
"createdAt": "2017-07-01T22:35:57.695Z"
}
Creates a new service contract.
Parameters
Parameter | In | Type | Required | Description |
---|---|---|---|---|
ContractRequest | body | string | correlationId | The request to create a new contract. |
Schema
Properties | Type | Description |
---|---|---|
correlationId | string | Requestor generated globally unique identifier for correleating requests. |
arguments | array |
HTTP Request
POST http://localhost/contracts
Get Service Contract
Example request:
curl 'http://localhost/contracts/f2c0244d-8473-417a-98ce-f30a979e925a'
ServiceClient client = new ServiceClient("http://localhost");
Contract contract = client.getContract("f2c0244d-8473-417a-98ce-f30a979e925a");
Returned response:
{
"id" : "f2c0244d-8473-417a-98ce-f30a979e925a",
"correlationId" : "8bbcbe9c-4955-4fd6-b97b-0bf3e8b5809f",
"status": "executed",
"btcAmount": "1.00",
"requiredArkAmount" : "2250.00",
"serviceArkAddress": "AewU1vEmPrtQNjdVo33cX84bfovY3jNAkV",
"returnArkAddress" : "ARNJJruY6RcuYCXcwWsu4bx9kyZtntqeAx",
"returnArkAmount": "50.00",
"arkPaymentTransactionId": "iefa85381c5c3c70f96d848df53ab7ed6135a7fb34b43e8f91f6j42018bf1258",
"returnArkTransactionId": "49f55381c5c3c70f96d848df53ab7f9ae9881dbb8eb43e8f91f642018bf1258f",
"bitcoinTransactionId": "2f12236a2684264ff33c7f1ce28ea9ed6135a7fb34af4185d504b6022fba8f77",
"createdAt": "2017-07-01T22:35:57.695Z",
"executedAt": "2017-07-01T22:35:58.000Z"
}
Gets service contract info for a contract.
Parameters
Parameter | In | Type | Required | Description |
---|---|---|---|---|
id | path | string | true | Contract identifier. |
HTTP Request
GET http://localhost/contracts/{id}