By Steffen Prohaska
The API is accessible at the same URL as the app, using a prefix. The paths for the API methods are described relative to the prefix. Clients are encouraged to request a specific API version.
The current version is at:
https://<host>/api/v1
Data is organized in repos, like in git. A repo contains mutable state,
primarily refs. refs are like git refs. By convention, we currently use only
branches/master
(which corresponds to heads/master
in git). We will
probably define a meaning for other prefixes later (like tags).
As in git, a ref points to a commit. Like a git commit, a nog commit contains information about authors, dates, a message, and so on. A commit points to parent commits and to a tree. Unlike a git commit, a nog commit can contain a dictionary of metadata, which may be useful when implementing specific workflows.
A tree has a name, a dictionary of metadata, and a list of child entries
of
format {type: object|tree, sha1: <id>}
. Tree is a recursive data structure.
The leaf nodes are objects. Objects also have a name and a metadata
dictionary; and they can point to a blob. A blob represents a binary object
that is stored in object storage (currently S3).
Trees can be used similar to a file system or a git tree. A main difference is that the nog tree entries are an ordered list and may contain entries with duplicate names. By convention, we usually avoid duplicate names and use a tree like a hierarchical file system.
We use conventions to give some trees and objects a certain meaning. Objects
with name *.md
are assumed to contain markdown in text
with blob=null
.
Objects that are named like an image file, like *.png
, are expected to have
a blob that contains the binary image data. An example for a convention on
trees is meta.workspace
. If it is present, the tree is expected to represent
a workspace with certain entries, like datalist
, programs
, jobs
, and
results
.
Immutable content has an id that is computed as the sha1 over a canonical JSON
format (see below for technical details). The documents stored in the database
may contain additional non-essential fields that are not part of the canonical
format. The most obvious example is _id
, which is the computed sha1.
Updates to a repo work similar to git on a low level: Get the ref, then the
commit for branches/master
. Then get the tree and modify it; or construct
a new tree from scratch; only the result matters. Construct a commit that
points to the tree and to the previous commit. Post everything in dependency
order, and finally update the ref, passing in the previous state as a nonce in
order to protect against concurrent writes. It should be clear how to do
this with the API routes below. Language bindings may offer convenience
functions that operate on a higher level and use caching. Since all content
is immutable (except for repos), caching is easy.
All immutable content entries (such as objects, trees and commits) have ids
that are computed as sha1s over a canonical EJSON format. The input content
is a minimal format (without href
) that includes all optional fields. See
examples below at 'create a commit', 'create an object', and 'create a tree'.
The canonical EJSON format is JSON with UTF-8-encoded strings, sorted keys, and
separators without whitespace.
There may be several different canonical formats for entry types. The format
version that must be used to reproduce the sha1 id is indicated by an integer
_idversion
. Clients should always be updated as soon as possible to handle
new versions correctly and keep code to handle older versions for
compatibility. Clients should check the _idversion
and handle an unknown
version as an error.
The details for each version are documented below at the respective 'create a ...' sections. Briefly:
- Commit format 0 supported only UTC Z date times.
- Commit format 1 added timezone support.
- Object format 0 by convention used
meta.content
for fulltext. - Object format 1 added a toplevel field
text
to store fulltext. - Tree format 0 is the only tree format.
_idversion
is not part of the canonical content and must be removed before
computing the sha1. errata
(see below) must also be removed.
Computing an id in CoffeeScript:
sha1Hex = (d) -> CryptoJS.SHA1(d).toString()
contentId = (content) -> sha1Hex(EJSON.stringify(content, {canonical: true}))
Computing an id in Python:
def stringify_canonical(content):
return json.dumps(
content, sort_keys=True, ensure_ascii=False, separators=(',', ':'),
).encode('utf-8')
def contentId(content):
h = hashlib.sha1()
h.update(stringify_canonical(content))
return h.hexdigest()
Due to a bug in the client-side SHA1 computation in browsers, correct blob data was stored under an incorrect blob id in a few cases during early development. The blobs and objects became part of the commit history. We wanted to keep the history but somehow mark the incorrect objects.
Since entries are immutable, the inconsistent ids cannot be modified but must
remain part of the immutable history. To handle such situations, content
entries can have an optional field errata
with a list of errata codes.
errata
must be removed when verifying the entry's id. The meaning of the
errata codes is deployment-specific.
The API uses a digital signature for authentication that is appended to the URL as a query string.
The following CoffeeScript code implements the signature process:
## Encode without ':' and strip milliseconds, since they are irrelevant.
toISOStringUrlsafe = (date) -> date.toISOString().replace(/:|\.[^Z]*/g, '')
NogAuth.signRequest = (key, req) ->
authalgorithm = 'nog-v1'
authkeyid = key.keyid
now = new Date()
authdate = toISOStringUrlsafe(now)
authexpires = config.defaultExpires
authnonce = crypto.randomBytes(10).toString('hex')
if urlparse(req.url).query?
req.url += '&'
else
req.url += '?'
req.url += "authalgorithm=#{authalgorithm}"
req.url += '&' + "authkeyid=#{authkeyid}"
req.url += '&' + "authdate=#{authdate}"
req.url += '&' + "authexpires=#{authexpires}"
req.url += '&' + "authnonce=#{authnonce}"
stringToSign = req.method + "\n" + req.url + "\n"
hmac = crypto.createHmac 'sha256', key.secretkey
hmac.update stringToSign
authsignature = hmac.digest 'hex'
req.url += '&' + "authsignature=#{authsignature}"
The method and the whole URL path are signed. The authsignature
must be
appended as the last query parameter.
authexpires
is specified in seconds.
The authnonce
is optional. If it is present, the request will be accepted
only once. The authnonce
needs to be unique only per authdate
, so a small
nonce is usually sufficient.
sign-req
, available from the
nog-starter-pack,
can be used to sign requests for curl:
Example:
export NOG_KEYID=<copied>
export NOG_SECRETKEY=<copied>
curl $(
./tools/bin/sign-req GET \
http://localhost:3000/api/blobs/31968d2e8b58e29e63851cb4b340216026f11f69
) | python -m json.tool
The following code implements the signature process in Python:
def sign_req(method, url):
authkeyid = os.environ['NOG_KEYID']
secretkey = os.environ['NOG_SECRETKEY'].encode()
authalgorithm = 'nog-v1'
authdate = datetime.utcnow().strftime('%Y-%m-%dT%H%M%SZ')
authexpires = '600'
authnonce = binascii.hexlify(os.urandom(5))
parsed = urlparse(url)
if parsed.query == '':
path = parsed.path
suffix = '?'
else:
path = parsed.path + '?' + parsed.query
suffix = '&'
suffix = suffix + 'authalgorithm=' + authalgorithm
suffix = suffix + '&authkeyid=' + authkeyid
suffix = suffix + '&authdate=' + authdate
suffix = suffix + '&authexpires=' + authexpires
suffix = suffix + '&authnonce=' + authnonce
stringToSign = (method + '\n' + path + suffix + '\n').encode()
authsignature = hexlify(hmac.new(
secretkey, stringToSign, digestmod=hashlib.sha256
).digest()).decode()
suffix = suffix + '&authsignature=' + authsignature
return url + suffix
POST /repos
Request body
repoFullName
(String
of format<owner>/<name>
): The name of the repository
Example:
{
"repoFullName": "fred/hello-world"
}
Response
Status: 201
{
"data": {
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world",
"id": "8rNFhDWE6x42io2Hq"
},
"fullName": "fred/hello-world",
"name": "hello-world",
"owner": "fred",
"ownerId": "g8dB4y3DYSPQfeXkL",
"refs": {
"branches/master": "0000000000000000000000000000000000000000"
}
},
"statusCode": 201
}
GET /repos/:repoOwner/:repoName/db/refs/:refName
Response
Status: 200
{
"data": {
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/refs/branches/master",
"refName": "branches/master"
},
"entry": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/commits/7215f2bb2b2128da2abb00b90e2be2f0274016cc",
"sha1": "7215f2bb2b2128da2abb00b90e2be2f0274016cc",
"type": "commit"
}
},
"statusCode": 200
}
GET /repos/:repoOwner/:repoName/db/refs
Response
Status: 200
{
"data": {
"count": 2,
"items": [
{
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/refs/branches/master",
"refName": "branches/master"
},
"entry": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/commits/7215f2bb2b2128da2abb00b90e2be2f0274016cc",
"sha1": "7215f2bb2b2128da2abb00b90e2be2f0274016cc",
"type": "commit"
}
},
{
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/refs/branches/foo/bar",
"refName": "branches/foo/bar"
},
"entry": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/commits/7215f2bb2b2128da2abb00b90e2be2f0274016cc",
"sha1": "7215f2bb2b2128da2abb00b90e2be2f0274016cc",
"type": "commit"
}
}
]
},
"statusCode": 200
}
PATCH /repos/:repoOwner/:repoName/db/refs/:refName
Request body
new
(String
): The new value of the reference (a hex sha1).old
(String
): The old value of the reference (a hex sha1).
The old value must be specified as a safety measure against accidentally
overwriting a reference that has been modified by someone else. null
or
0000000000000000000000000000000000000000
can be used to indicate that the
reference is unset.
Example:
{
"new": "7215f2bb2b2128da2abb00b90e2be2f0274016cc",
"old": "0000000000000000000000000000000000000000"
}
Response
Status: 200
{
"data": {
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/refs/branches/master",
"refName": "branches/master"
},
"entry": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/commits/7215f2bb2b2128da2abb00b90e2be2f0274016cc",
"sha1": "7215f2bb2b2128da2abb00b90e2be2f0274016cc",
"type": "commit"
}
},
"statusCode": 200
}
DELETE /repos/:repoOwner/:repoName/db/refs/:refName
Request body
old
(String
): The old value of the reference (a hex sha1).
The old value must be specified as a safety measure against accidentally deleting a reference that has been modified by someone else.
Example:
{
"old": "7215f2bb2b2128da2abb00b90e2be2f0274016cc"
}
Response
Status: 204
GET /repos/:repoOwner/:repoName/db/commits/:sha1?format=:format
Request query params
format=:format
(minimal
orhrefs
with optional suffix.v0
of.v1
; default:hrefs
): Specifies whether the result contains a minimal representation or embedded hrefs. The suffix specifies which representation version to return. The default without suffix is to return the representation that matches_idversion
.
Response
With hrefs:
GET http://localhost:3000/api/repos/fred/hello-world/db/commits/7215f2bb2b2128da2abb00b90e2be2f0274016cc?format=hrefs
Status: 200
{
"data": {
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/commits/7215f2bb2b2128da2abb00b90e2be2f0274016cc",
"sha1": "7215f2bb2b2128da2abb00b90e2be2f0274016cc"
},
"_idversion": 1,
"authorDate": "2016-02-18T06:14:20+00:00",
"authors": [
"unknown <unknown>"
],
"commitDate": "2016-02-18T06:14:20+00:00",
"committer": "unknown <unknown>",
"message": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed\ndo eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco\nlaboris nisi ut aliquip ex ea commodo consequat.\n",
"meta": {
"importGitCommit": "1919191919191919191919191919191919191919"
},
"parents": [
{
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/commits/6812c564e1b0b4c4abd6d1fa75f467f0e57079d4",
"sha1": "6812c564e1b0b4c4abd6d1fa75f467f0e57079d4"
}
],
"subject": "Initial commit",
"tree": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/trees/be9cd0d3d9150ac633e317f78d01a71f40077e94",
"sha1": "be9cd0d3d9150ac633e317f78d01a71f40077e94"
}
},
"statusCode": 200
}
With hrefs, representation v0 with UTC Z datetimes:
GET http://localhost:3000/api/repos/fred/hello-world/db/commits/86e03b3720b912ff3ae6de494464f8a764597778?format=hrefs.v0
Status: 200
{
"data": {
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/commits/86e03b3720b912ff3ae6de494464f8a764597778",
"sha1": "86e03b3720b912ff3ae6de494464f8a764597778"
},
"_idversion": 0,
"authorDate": "2015-01-01T00:00:00Z",
"authors": [
"unknown <unknown>"
],
"commitDate": "2015-01-01T00:00:00Z",
"committer": "unknown <unknown>",
"message": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed\ndo eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco\nlaboris nisi ut aliquip ex ea commodo consequat.\n",
"meta": {},
"parents": [],
"subject": "Initial commit",
"tree": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/trees/5af3a99f790fc7cfee9622b35564585c8d4df64a",
"sha1": "5af3a99f790fc7cfee9622b35564585c8d4df64a"
}
},
"statusCode": 200
}
With hrefs, representation v1 with UTC timezone support:
Note that _idversion
and format version may differ. To compute the correct
id, the client code must convert the dates to the correct _idversion
, which
is UTC Z for _idversion: 0
.
GET http://localhost:3000/api/repos/fred/hello-world/db/commits/7215f2bb2b2128da2abb00b90e2be2f0274016cc?format=hrefs.v1
Status: 200
{
"data": {
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/commits/7215f2bb2b2128da2abb00b90e2be2f0274016cc",
"sha1": "7215f2bb2b2128da2abb00b90e2be2f0274016cc"
},
"_idversion": 1,
"authorDate": "2016-02-18T06:14:20+00:00",
"authors": [
"unknown <unknown>"
],
"commitDate": "2016-02-18T06:14:20+00:00",
"committer": "unknown <unknown>",
"message": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed\ndo eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco\nlaboris nisi ut aliquip ex ea commodo consequat.\n",
"meta": {
"importGitCommit": "1919191919191919191919191919191919191919"
},
"parents": [
{
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/commits/6812c564e1b0b4c4abd6d1fa75f467f0e57079d4",
"sha1": "6812c564e1b0b4c4abd6d1fa75f467f0e57079d4"
}
],
"subject": "Initial commit",
"tree": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/trees/be9cd0d3d9150ac633e317f78d01a71f40077e94",
"sha1": "be9cd0d3d9150ac633e317f78d01a71f40077e94"
}
},
"statusCode": 200
}
Minimal:
GET http://localhost:3000/api/repos/fred/hello-world/db/commits/7215f2bb2b2128da2abb00b90e2be2f0274016cc?format=minimal
Status: 200
{
"data": {
"_id": "7215f2bb2b2128da2abb00b90e2be2f0274016cc",
"_idversion": 1,
"authorDate": "2016-02-18T06:14:20+00:00",
"authors": [
"unknown <unknown>"
],
"commitDate": "2016-02-18T06:14:20+00:00",
"committer": "unknown <unknown>",
"message": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed\ndo eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco\nlaboris nisi ut aliquip ex ea commodo consequat.\n",
"meta": {
"importGitCommit": "1919191919191919191919191919191919191919"
},
"parents": [
"6812c564e1b0b4c4abd6d1fa75f467f0e57079d4"
],
"subject": "Initial commit",
"tree": "be9cd0d3d9150ac633e317f78d01a71f40077e94"
},
"statusCode": 200
}
Minimal, representation v0 with UTC Z datetimes:
GET http://localhost:3000/api/repos/fred/hello-world/db/commits/86e03b3720b912ff3ae6de494464f8a764597778?format=minimal.v0
Status: 200
{
"data": {
"_id": "86e03b3720b912ff3ae6de494464f8a764597778",
"_idversion": 0,
"authorDate": "2015-01-01T00:00:00Z",
"authors": [
"unknown <unknown>"
],
"commitDate": "2015-01-01T00:00:00Z",
"committer": "unknown <unknown>",
"message": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed\ndo eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco\nlaboris nisi ut aliquip ex ea commodo consequat.\n",
"meta": {},
"parents": [],
"subject": "Initial commit",
"tree": "5af3a99f790fc7cfee9622b35564585c8d4df64a"
},
"statusCode": 200
}
Minimal, representation v1 with UTC timezone support:
GET http://localhost:3000/api/repos/fred/hello-world/db/commits/7215f2bb2b2128da2abb00b90e2be2f0274016cc?format=minimal.v1
Status: 200
{
"data": {
"_id": "7215f2bb2b2128da2abb00b90e2be2f0274016cc",
"_idversion": 1,
"authorDate": "2016-02-18T06:14:20+00:00",
"authors": [
"unknown <unknown>"
],
"commitDate": "2016-02-18T06:14:20+00:00",
"committer": "unknown <unknown>",
"message": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed\ndo eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco\nlaboris nisi ut aliquip ex ea commodo consequat.\n",
"meta": {
"importGitCommit": "1919191919191919191919191919191919191919"
},
"parents": [
"6812c564e1b0b4c4abd6d1fa75f467f0e57079d4"
],
"subject": "Initial commit",
"tree": "be9cd0d3d9150ac633e317f78d01a71f40077e94"
},
"statusCode": 200
}
POST /repos/:repoOwner/:repoName/db/commits?format=:format
Request query params
format=:format
(minimal
orhrefs
with optional suffix.v0
or.v1
; default:hrefs
): Specifies whether the result is a minimal representation or contains embedded hrefs (see example at get).
Request body
The body contains a JSON representation of the commit with the following keys:
subject
(String
): The subject line of the commit.message
(String
): The body of the commit message.tree
(String
): The id of the tree as a hex sha1.parents
([String]
): The ids of the parent commits as hex sha1s. The array may be empty.authors
([String]
, optional): An array of authors, by conventionJohn Q. Public <[email protected]>
.authorDate
(String
, optional): An ISO string without fractional seconds (see below for_idversion
).committer
(String
, optional)commitDate
(String
, optional): An ISO string without fractional seconds (see below for_idversion
).meta
(Object
, optional): Meta data that is stored with the commit._idversion
(0
or1
, default1
): Specify format to use for computing the sha1 id.
The date format differs between representation versions:
_idversion 0
: Dates are UTC with Z timezone indicator._idversion 1
: Dates use a timezone offset+HH:MM
or-HH:MM
.
Example:
{
"message": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed\ndo eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco\nlaboris nisi ut aliquip ex ea commodo consequat.\n",
"meta": {
"importGitCommit": "1919191919191919191919191919191919191919"
},
"parents": [
"6812c564e1b0b4c4abd6d1fa75f467f0e57079d4"
],
"subject": "Initial commit",
"tree": "be9cd0d3d9150ac633e317f78d01a71f40077e94"
}
Response
Status: 201
{
"data": {
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/commits/7215f2bb2b2128da2abb00b90e2be2f0274016cc",
"sha1": "7215f2bb2b2128da2abb00b90e2be2f0274016cc"
},
"_idversion": 1,
"authorDate": "2016-02-18T06:14:20+00:00",
"authors": [
"unknown <unknown>"
],
"commitDate": "2016-02-18T06:14:20+00:00",
"committer": "unknown <unknown>",
"message": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed\ndo eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco\nlaboris nisi ut aliquip ex ea commodo consequat.\n",
"meta": {
"importGitCommit": "1919191919191919191919191919191919191919"
},
"parents": [
{
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/commits/6812c564e1b0b4c4abd6d1fa75f467f0e57079d4",
"sha1": "6812c564e1b0b4c4abd6d1fa75f467f0e57079d4"
}
],
"subject": "Initial commit",
"tree": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/trees/be9cd0d3d9150ac633e317f78d01a71f40077e94",
"sha1": "be9cd0d3d9150ac633e317f78d01a71f40077e94"
}
},
"statusCode": 201
}
Commit idversion 0
:
POST /repos/:repoOwner/:repoName/db/commits?format=:format
{
"_idversion": 0,
"authorDate": "2015-01-01T00:00:00Z",
"commitDate": "2015-01-01T00:00:00Z",
"message": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed\ndo eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco\nlaboris nisi ut aliquip ex ea commodo consequat.\n",
"parents": [],
"subject": "Initial commit",
"tree": "5af3a99f790fc7cfee9622b35564585c8d4df64a"
}
Response
Status: 201
{
"data": {
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/commits/86e03b3720b912ff3ae6de494464f8a764597778",
"sha1": "86e03b3720b912ff3ae6de494464f8a764597778"
},
"_idversion": 0,
"authorDate": "2015-01-01T00:00:00Z",
"authors": [
"unknown <unknown>"
],
"commitDate": "2015-01-01T00:00:00Z",
"committer": "unknown <unknown>",
"message": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed\ndo eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco\nlaboris nisi ut aliquip ex ea commodo consequat.\n",
"meta": {},
"parents": [],
"subject": "Initial commit",
"tree": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/trees/5af3a99f790fc7cfee9622b35564585c8d4df64a",
"sha1": "5af3a99f790fc7cfee9622b35564585c8d4df64a"
}
},
"statusCode": 201
}
GET /repos/:repoOwner/:repoName/db/objects/:sha1?format=:format
Request query params
format=:format
(minimal
orhrefs
with optional suffix.v0
or.v1
; default:hrefs
): Specifies whether the result contains a minimal representation or embedded hrefs.
Response
With hrefs:
GET http://localhost:3000/api/repos/fred/hello-world/db/objects/d46126638a13e0b86adc09d15670c8cfeb19373b?format=hrefs
Status: 200
{
"data": {
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/objects/d46126638a13e0b86adc09d15670c8cfeb19373b",
"sha1": "d46126638a13e0b86adc09d15670c8cfeb19373b"
},
"_idversion": 1,
"blob": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/blobs/3f786850e387550fdab836ed7e6dc881de23001b",
"sha1": "3f786850e387550fdab836ed7e6dc881de23001b"
},
"meta": {
"random": "bukxwstgav",
"specimen": "bar",
"study": "foo"
},
"name": "Fake data",
"text": null
},
"statusCode": 200
}
Minimal:
GET http://localhost:3000/api/repos/fred/hello-world/db/objects/d46126638a13e0b86adc09d15670c8cfeb19373b?format=minimal
Status: 200
{
"data": {
"_id": "d46126638a13e0b86adc09d15670c8cfeb19373b",
"_idversion": 1,
"blob": "3f786850e387550fdab836ed7e6dc881de23001b",
"meta": {
"random": "bukxwstgav",
"specimen": "bar",
"study": "foo"
},
"name": "Fake data",
"text": null
},
"statusCode": 200
}
Minimal, explicit format version 0:
Note that _idversion
and format version may differ. To compute the correct
sha1, the client must convert the format to the _idversion
that the server
reported.
GET http://localhost:3000/api/repos/fred/hello-world/db/objects/5541d329b004502cbed1d97f037dcf20527fd29f?format=minimal.v0
Status: 200
{
"data": {
"_id": "5541d329b004502cbed1d97f037dcf20527fd29f",
"_idversion": 0,
"blob": "0000000000000000000000000000000000000000",
"meta": {
"content": "Lorem ipsum...",
"random": "syskehmxsk"
},
"name": "fake-index.md"
},
"statusCode": 200
}
Minimal, explicit format version 1:
GET http://localhost:3000/api/repos/fred/hello-world/db/objects/5541d329b004502cbed1d97f037dcf20527fd29f?format=minimal.v1
Status: 200
{
"data": {
"_id": "5541d329b004502cbed1d97f037dcf20527fd29f",
"_idversion": 0,
"blob": null,
"meta": {
"random": "syskehmxsk"
},
"name": "fake-index.md",
"text": "Lorem ipsum..."
},
"statusCode": 200
}
POST /repos/:repoOwner/:repoName/db/objects?format=:format
Request query params
format=:format
(minimal
orhrefs
; default:hrefs
): Specifies whether the result is a minimal representation or contains embedded hrefs (see example at get)
Request body
The body contains a JSON representation of the object with the following keys:
blob
(String
ornull
): The identifier of the associated blob (a hex sha1).text
(String
ornull
; since format version 1): Text content of the object. Text content is indexed for fulltext search, while blob content is opaque. By convention either useblob
ortext
, or none of them; but do not use both at the same time.name
(String
): The name of the object.meta
(Object
): Meta data that is stored with the object._idversion
(0
or1
, default1
): Specify the format to use for computing the sha1 id.
There are two different format versions:
_idversion 0
: Absence of a blob is indicated by0000000000000000000000000000000000000000
. Fulltext is, by convention, stored inmeta.content
._idversion 1
: Absence of a blob is indicated bynull
. Fulltext is stored intext
(may benull
).
Example:
{
"blob": "3f786850e387550fdab836ed7e6dc881de23001b",
"meta": {
"random": "elkqaanymh",
"specimen": "bar",
"study": "foo"
},
"name": "Fake data"
}
Response
Status: 201
{
"data": {
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/objects/15635f828b11153643f932b3e57fd9f527a4be66",
"sha1": "15635f828b11153643f932b3e57fd9f527a4be66"
},
"_idversion": 1,
"blob": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/blobs/3f786850e387550fdab836ed7e6dc881de23001b",
"sha1": "3f786850e387550fdab836ed7e6dc881de23001b"
},
"meta": {
"random": "elkqaanymh",
"specimen": "bar",
"study": "foo"
},
"name": "Fake data",
"text": null
},
"statusCode": 201
}
Object with idversion 0 layout:
POST /repos/:repoOwner/:repoName/db/objects?format=:format
{
"_idversion": 0,
"blob": null,
"meta": {
"content": "Lorem ipsum...",
"random": "syskehmxsk"
},
"name": "fake-index.md"
}
Response
Status: 201
{
"data": {
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/objects/5541d329b004502cbed1d97f037dcf20527fd29f",
"sha1": "5541d329b004502cbed1d97f037dcf20527fd29f"
},
"_idversion": 0,
"blob": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/blobs/0000000000000000000000000000000000000000",
"sha1": "0000000000000000000000000000000000000000"
},
"meta": {
"content": "Lorem ipsum...",
"random": "syskehmxsk"
},
"name": "fake-index.md"
},
"statusCode": 201
}
GET /repos/:repoOwner/:repoName/db/trees/:sha1?expand=:levels&format=:format
Request query params
expand=:levels
(non-negative integer, optional): Specifies how many entry levels will be expanded recursively. 0 indicates no expansion.format=:format
(minimal
orhrefs
with optional suffix.v0
; default:hrefs
): Specifies whether the result contains a minimal representation or embedded hrefs.
The optional format
version suffix may only be used with expand=0
.
Children will always be expanded in the format that matches their _idversion
.
Response
Unexpanded:
GET http://localhost:3000/api/repos/fred/hello-world/db/trees/be9cd0d3d9150ac633e317f78d01a71f40077e94?expand=0&format=hrefs
Status: 200
{
"data": {
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/trees/be9cd0d3d9150ac633e317f78d01a71f40077e94",
"sha1": "be9cd0d3d9150ac633e317f78d01a71f40077e94"
},
"_idversion": 0,
"entries": [
{
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/objects/d46126638a13e0b86adc09d15670c8cfeb19373b",
"sha1": "d46126638a13e0b86adc09d15670c8cfeb19373b",
"type": "object"
},
{
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/objects/b4556ff729e1d49a25cf90c19b5bf8df8ce88a4f",
"sha1": "b4556ff729e1d49a25cf90c19b5bf8df8ce88a4f",
"type": "object"
}
],
"meta": {
"study": "foo"
},
"name": "Workspace root"
},
"statusCode": 200
}
Expanded:
GET http://localhost:3000/api/repos/fred/hello-world/db/trees/be9cd0d3d9150ac633e317f78d01a71f40077e94?expand=1&format=hrefs
Status: 200
{
"data": {
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/trees/be9cd0d3d9150ac633e317f78d01a71f40077e94",
"sha1": "be9cd0d3d9150ac633e317f78d01a71f40077e94"
},
"_idversion": 0,
"entries": [
{
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/objects/d46126638a13e0b86adc09d15670c8cfeb19373b",
"sha1": "d46126638a13e0b86adc09d15670c8cfeb19373b"
},
"_idversion": 1,
"blob": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/blobs/3f786850e387550fdab836ed7e6dc881de23001b",
"sha1": "3f786850e387550fdab836ed7e6dc881de23001b"
},
"meta": {
"random": "bukxwstgav",
"specimen": "bar",
"study": "foo"
},
"name": "Fake data",
"text": null
},
{
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/objects/b4556ff729e1d49a25cf90c19b5bf8df8ce88a4f",
"sha1": "b4556ff729e1d49a25cf90c19b5bf8df8ce88a4f"
},
"_idversion": 1,
"blob": null,
"meta": {
"random": "gotlxwjvxj"
},
"name": "index.md",
"text": "Lorem ipsum..."
}
],
"meta": {
"study": "foo"
},
"name": "Workspace root"
},
"statusCode": 200
}
Expanded, minimal:
GET http://localhost:3000/api/repos/fred/hello-world/db/trees/be9cd0d3d9150ac633e317f78d01a71f40077e94?expand=1&format=minimal
Status: 200
{
"data": {
"_id": "be9cd0d3d9150ac633e317f78d01a71f40077e94",
"_idversion": 0,
"entries": [
{
"_id": "d46126638a13e0b86adc09d15670c8cfeb19373b",
"_idversion": 1,
"blob": "3f786850e387550fdab836ed7e6dc881de23001b",
"meta": {
"random": "bukxwstgav",
"specimen": "bar",
"study": "foo"
},
"name": "Fake data",
"text": null
},
{
"_id": "b4556ff729e1d49a25cf90c19b5bf8df8ce88a4f",
"_idversion": 1,
"blob": null,
"meta": {
"random": "gotlxwjvxj"
},
"name": "index.md",
"text": "Lorem ipsum..."
}
],
"meta": {
"study": "foo"
},
"name": "Workspace root"
},
"statusCode": 200
}
POST /repos/:repoOwner/:repoName/db/trees?format=:format
Request query params
format=:format
(minimal
orhrefs
; default:hrefs
): Specifies whether the result is a minimal representation or contains embedded hrefs (see example at get)
Request body
The body contains a JSON representation of the tree with the following keys:
tree.name
(String
): The name of the object.tree.meta
(Object
): Meta data that is stored with the object.tree.entries
(Array
of entries): An entry can either be collapsed{"type": <type>, "sha1": <sha1>}
, where<type>
can be'object'
or'tree'
and<sha1>
must be the id of a corresponding entry; or an entry can contain the full content for an object or tree.
There is only a single canonical representation (_idversion: 0
) for trees.
Trees may recursively contain trees up to the total request limit. Consider using a series of bulk posts (see below) if the total tree size exceeds the limit.
Example with collapsed entry:
{
"tree": {
"entries": [
{
"sha1": "15635f828b11153643f932b3e57fd9f527a4be66",
"type": "object"
}
],
"meta": {
"study": "foo"
},
"name": "Workspace root"
}
}
Example with expanded entry:
{
"tree": {
"entries": [
{
"blob": "3f786850e387550fdab836ed7e6dc881de23001b",
"meta": {
"random": "bukxwstgav",
"specimen": "bar",
"study": "foo"
},
"name": "Fake data"
},
{
"_idversion": 1,
"blob": null,
"meta": {
"random": "gotlxwjvxj"
},
"name": "index.md",
"text": "Lorem ipsum..."
}
],
"meta": {
"study": "foo"
},
"name": "Workspace root"
}
}
Response
Status: 201
{
"data": {
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/trees/be9cd0d3d9150ac633e317f78d01a71f40077e94",
"sha1": "be9cd0d3d9150ac633e317f78d01a71f40077e94"
},
"_idversion": 0,
"entries": [
{
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/objects/d46126638a13e0b86adc09d15670c8cfeb19373b",
"sha1": "d46126638a13e0b86adc09d15670c8cfeb19373b",
"type": "object"
},
{
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/objects/b4556ff729e1d49a25cf90c19b5bf8df8ce88a4f",
"sha1": "b4556ff729e1d49a25cf90c19b5bf8df8ce88a4f",
"type": "object"
}
],
"meta": {
"study": "foo"
},
"name": "Workspace root"
},
"statusCode": 201
}
POST /repos/:repoOwner/:repoName/db/bulk
Request body
entries
(Array of expanded entries or copy instructions): Expanded entries can be objects, trees, and commits. If entries depend on each other, the entries must be ordered such that entries that depend on other entries come after their dependencies. A special kind of entry can be used to copy content from other repos:{"copy": {"type": String, "sha1": String, "repoFullName": String}}
copies the entry with thesha1
from the repo with namerepoFullName
.type
can beobject
,tree
,commit
, orblob
.
Example:
{
"entries": [
{
"blob": "3f786850e387550fdab836ed7e6dc881de23001b",
"meta": {
"random": "elkqaanymh",
"specimen": "bar",
"study": "foo"
},
"name": "Fake data"
},
{
"entries": [
{
"sha1": "15635f828b11153643f932b3e57fd9f527a4be66",
"type": "object"
}
],
"meta": {
"study": "foo"
},
"name": "Workspace root"
},
{
"message": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed\ndo eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco\nlaboris nisi ut aliquip ex ea commodo consequat.\n",
"meta": {
"importGitCommit": "1919191919191919191919191919191919191919"
},
"parents": [
"f14b966459667078910b9a8fcf77b5f3228f7f1e"
],
"subject": "Initial commit",
"tree": "5af3a99f790fc7cfee9622b35564585c8d4df64a"
},
{
"copy": {
"repoFullName": "fred/hello-world",
"sha1": "15635f828b11153643f932b3e57fd9f527a4be66",
"type": "object"
}
},
{
"copy": {
"repoFullName": "fred/hello-world",
"sha1": "5af3a99f790fc7cfee9622b35564585c8d4df64a",
"type": "tree"
}
}
]
}
Response
An array of collapsed entries
of format {"type": String, "sha1": String}
.
Status: 201
{
"data": {
"entries": [
{
"sha1": "15635f828b11153643f932b3e57fd9f527a4be66",
"type": "object"
},
{
"sha1": "5af3a99f790fc7cfee9622b35564585c8d4df64a",
"type": "tree"
},
{
"sha1": "a4e46e4265fc4dd0169cdc17001f9275aa739255",
"type": "commit"
},
{
"sha1": "15635f828b11153643f932b3e57fd9f527a4be66",
"type": "object"
},
{
"sha1": "5af3a99f790fc7cfee9622b35564585c8d4df64a",
"type": "tree"
}
]
},
"statusCode": 201
}
POST /repos/:repoOwner/:repoName/db/stat
The method is POST
, because it seems controversial whether request bodies
should be used with GET
.
Request body
entries
(Array of{"type": String, "sha1": String}
): The entries for which status information is requested.type
can beobject
,tree
,commit
, orblob
.sha1
is a hex sha1 id of the entry.
Example:
{
"entries": [
{
"sha1": "d46126638a13e0b86adc09d15670c8cfeb19373b",
"type": "object"
},
{
"sha1": "be9cd0d3d9150ac633e317f78d01a71f40077e94",
"type": "tree"
},
{
"sha1": "7215f2bb2b2128da2abb00b90e2be2f0274016cc",
"type": "commit"
},
{
"sha1": "0123012301230123012301230123012301230123",
"type": "object"
}
]
}
Response
The entries
array that was posted is echoed back with an additional field
status
that contains exists
or unknown
.
Status: 200
{
"data": {
"entries": [
{
"sha1": "d46126638a13e0b86adc09d15670c8cfeb19373b",
"status": "exists",
"type": "object"
},
{
"sha1": "be9cd0d3d9150ac633e317f78d01a71f40077e94",
"status": "exists",
"type": "tree"
},
{
"sha1": "7215f2bb2b2128da2abb00b90e2be2f0274016cc",
"status": "exists",
"type": "commit"
},
{
"sha1": "0123012301230123012301230123012301230123",
"status": "unknown",
"type": "object"
}
]
},
"statusCode": 200
}
GET /repos/:repoOwner/:repoName/db/blobs/:sha1
Response
Status: 200
{
"data": {
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/blobs/3f786850e387550fdab836ed7e6dc881de23001b",
"id": "3f786850e387550fdab836ed7e6dc881de23001b"
},
"content": {
"href": "https://some-s3-bucket.amazonaws.com/3f786850e387550fdab836ed7e6dc881de23001b?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKXXXXXXXXXXXXXXXXXX%2F20160218%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20160218T060613Z&X-Amz-Expires=900&X-Amz-Signature=cebc1eebb2665ed09b3460ef7c6dffaf3a13fb1f9f37fe83ac43bd519fdf9b7b&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D%223f786850e387550fdab836ed7e6dc881de23001b.dat%22"
},
"sha1": "3f786850e387550fdab836ed7e6dc881de23001b",
"size": 2,
"status": "available"
},
"statusCode": 200
}
GET /repos/:repoOwner/:repoName/db/blobs/:sha1/content
It will respond with a redirect to S3. The S3 URL will expire after a few minutes.
Response
Status: 307
Location: https://some-s3-bucket.amazonaws.com/3f786850e387550fdab836ed7e6dc881de23001b?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKXXXXXXXXXXXXXXXXXX%2F20160218%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20160218T060614Z&X-Amz-Expires=900&X-Amz-Signature=2df6dec751ae156f4559178d669b3c6e663ac9fd5a3446a181f475632d3d02f9&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D%223f786850e387550fdab836ed7e6dc881de23001b.dat%22
Uploading data requires a sequence of coordinated requests. The upload starts
with a POST
, which returns an upload id and descriptions how parts should be
upload to S3. Depending on the total upload size, multiple parts need to be
uploaded to S3. More upload parts should be requested only when needed and
used immediately, because the S3 URLs expire after a couple of minutes. After
uploading the binary data to S3, the upload is completed by posting the ETag
headers that S3 returned to the completion href that has been returned by the
initial POST
.
POST /repos/:repoOwner/:repoName/db/blobs/:sha1/uploads?limit=:limit
The sha1 of the file is specified in the path.
:limit
is used to restrict the number of upload parts that are initially
returned. Use a limit of 1 if your upload code works sequentially. You may
use a larger number if your upload code handles multiple concurrent uploads to
S3.
Request body
size
(Number
): The file size.name
(String
): The local file name.
Example:
POST https://nog.zib.de/api/repos/fred/hello-world/db/blobs/4c187d0d3e1df64c6e6365be78c13c276ff4cba4/uploads?limit=1
{
"name": "testdata.dat",
"size": 6000000
}
Response
Status: 201
{
"data": {
"parts": {
"count": 2,
"items": [
{
"end": 5242880,
"href": "https://some-s3-bucket.amazonaws.com/4c187d0d3e1df64c6e6365be78c13c276ff4cba4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKXXXXXXXXXXXXXXXXXX%2F20160218%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20160218T060332Z&X-Amz-Expires=900&X-Amz-Signature=f470a86511de484d603f743d911d2ecf250248d47ac5214ae5cc670fa717aae2&X-Amz-SignedHeaders=host&partNumber=1&uploadId=JbzKJWaG0.Q8kcQFLrb0wwfG_VNTq_ZT_W9JqtPtEyrob6RKKBiAXGRH717QwqzPvJopYTgCDD_2rfhwPjDnpiYkVE17fvSS6hIDFQkOyxwb.y5UT8hGJM4dGFbj8SO1",
"partNumber": 1,
"start": 0
}
],
"limit": 1,
"next": "https://nog.zib.de/api/repos/fred/hello-world/db/blobs/4c187d0d3e1df64c6e6365be78c13c276ff4cba4/uploads/JbzKJWaG0.Q8kcQFLrb0wwfG_VNTq_ZT_W9JqtPtEyrob6RKKBiAXGRH717QwqzPvJopYTgCDD_2rfhwPjDnpiYkVE17fvSS6hIDFQkOyxwb.y5UT8hGJM4dGFbj8SO1/parts?offset=1&limit=1",
"offset": 0
},
"upload": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/blobs/4c187d0d3e1df64c6e6365be78c13c276ff4cba4/uploads/JbzKJWaG0.Q8kcQFLrb0wwfG_VNTq_ZT_W9JqtPtEyrob6RKKBiAXGRH717QwqzPvJopYTgCDD_2rfhwPjDnpiYkVE17fvSS6hIDFQkOyxwb.y5UT8hGJM4dGFbj8SO1",
"id": "JbzKJWaG0.Q8kcQFLrb0wwfG_VNTq_ZT_W9JqtPtEyrob6RKKBiAXGRH717QwqzPvJopYTgCDD_2rfhwPjDnpiYkVE17fvSS6hIDFQkOyxwb.y5UT8hGJM4dGFbj8SO1"
}
},
"statusCode": 201
}
PUT <data.parts.items[n].href>
Binary data for each part must be send to S3 using PUT
. The data slice for
each part is specified as [start; end[
in the part descriptions. The start
is inclusive; the end is exclusive.
Pay attention to the indexing: S3 part numbers start with index 1. The pagination starts with index 0.
Example:
PUT https://some-s3-bucket.amazonaws.com/4c187d0d3e1df64c6e6365be78c13c276ff4cba4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKXXXXXXXXXXXXXXXXXX%2F20160218%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20160218T060355Z&X-Amz-Expires=900&X-Amz-Signature=fb376d6652691e44a0c28627d7adb1d0daaca97e5ca210f0a833498bab9bf721&X-Amz-SignedHeaders=host&partNumber=2&uploadId=JbzKJWaG0.Q8kcQFLrb0wwfG_VNTq_ZT_W9JqtPtEyrob6RKKBiAXGRH717QwqzPvJopYTgCDD_2rfhwPjDnpiYkVE17fvSS6hIDFQkOyxwb.y5UT8hGJM4dGFbj8SO1
Body with binary data for [start; end[
Response
Status: 200
ETag: "a6c5e0b78ec35e11070a7350daa82211"
GET <parts.next>
More parts can be retrieved from the next
href of the previous parts. The
URL automatically uses the same limit as the initial request.
An alternative is to explicitly construct the URL to get more parts:
GET /repos/:repoOwner/:repoName/db/blobs/:sha1/uploads/:uploadId?offset=:offset&limit=:limit
Example:
GET https://nog.zib.de/api/repos/fred/hello-world/db/blobs/4c187d0d3e1df64c6e6365be78c13c276ff4cba4/uploads/JbzKJWaG0.Q8kcQFLrb0wwfG_VNTq_ZT_W9JqtPtEyrob6RKKBiAXGRH717QwqzPvJopYTgCDD_2rfhwPjDnpiYkVE17fvSS6hIDFQkOyxwb.y5UT8hGJM4dGFbj8SO1/parts?offset=1&limit=1
Response
Status: 200
{
"data": {
"count": 2,
"items": [
{
"end": 6000000,
"href": "https://some-s3-bucket.amazonaws.com/4c187d0d3e1df64c6e6365be78c13c276ff4cba4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKXXXXXXXXXXXXXXXXXX%2F20160218%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20160218T060355Z&X-Amz-Expires=900&X-Amz-Signature=fb376d6652691e44a0c28627d7adb1d0daaca97e5ca210f0a833498bab9bf721&X-Amz-SignedHeaders=host&partNumber=2&uploadId=JbzKJWaG0.Q8kcQFLrb0wwfG_VNTq_ZT_W9JqtPtEyrob6RKKBiAXGRH717QwqzPvJopYTgCDD_2rfhwPjDnpiYkVE17fvSS6hIDFQkOyxwb.y5UT8hGJM4dGFbj8SO1",
"partNumber": 2,
"start": 5242880
}
],
"limit": 1,
"next": null,
"offset": 1
},
"statusCode": 200
}
The upload is completed by a POST
to the href that has been returned as
upload.href
when starting the upload.
POST <upload.href>
The format is:
POST /repos/:repoOwner/:repoName/db/blobs/:sha1/uploads/:uploadId
Example:
POST https://nog.zib.de/api/repos/fred/hello-world/db/blobs/4c187d0d3e1df64c6e6365be78c13c276ff4cba4/uploads/JbzKJWaG0.Q8kcQFLrb0wwfG_VNTq_ZT_W9JqtPtEyrob6RKKBiAXGRH717QwqzPvJopYTgCDD_2rfhwPjDnpiYkVE17fvSS6hIDFQkOyxwb.y5UT8hGJM4dGFbj8SO1
Request body
The body contains a field s3Parts
with an array with the part numbers and
ETag headers returned by S3.
Example:
{
"s3Parts": [
{
"ETag": "\"8220aff7f4c6452a8e7f8cd1be261365\"",
"PartNumber": 1
},
{
"ETag": "\"a6c5e0b78ec35e11070a7350daa82211\"",
"PartNumber": 2
}
]
}
Response
Status: 201
{
"data": {
"_id": {
"href": "https://nog.zib.de/api/repos/fred/hello-world/db/blobs/4c187d0d3e1df64c6e6365be78c13c276ff4cba4",
"id": "4c187d0d3e1df64c6e6365be78c13c276ff4cba4"
},
"content": {
"href": "https://some-s3-bucket.amazonaws.com/4c187d0d3e1df64c6e6365be78c13c276ff4cba4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKXXXXXXXXXXXXXXXXXX%2F20160218%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20160218T060401Z&X-Amz-Expires=900&X-Amz-Signature=8ac8c68a1f72db5a4e4e03c443f095b2dc6236d3f4a0a3803d888c1e6c8e7414&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D%224c187d0d3e1df64c6e6365be78c13c276ff4cba4.dat%22"
},
"sha1": "4c187d0d3e1df64c6e6365be78c13c276ff4cba4",
"size": 6000000,
"status": "available"
},
"statusCode": 201
}
GET /jobs/:jobId/status
Request query params
- None
Request body
- empty
Response
Status: 200
{
"data": {
"status": "completed"
},
"statusCode": 200
}
POST /jobs/:jobId/status
Request query params
- None
Request body
retryId (Integer)
: Current retry ID of this jobstatus (String)
: Either'completed'
,'running'
or'failed'
reason (String)
: Optional, reason if status is'failed'
Response
Status: 200
{
"data": {},
"statusCode": 200
}
GET /jobs/:jobId/progress
Request query params
- None
Request body
- empty
Response
Status: 200
{
"data": {
"progress": {
"completed": 1,
"percent": 50,
"total": 2
}
},
"statusCode": 200
}
POST /jobs/:jobId/progress
Request query params
- None
Request body
retryId (Integer)
: Current retry ID of this jobprogress (Object)
: withcompleted (Integer)
: Number of completed taskstotal (Integer)
: Number of total tasks
Response
Status: 200
{
"data": {},
"statusCode": 200
}
POST /jobs/:jobId/log
Request query params
- None
Request body
retryId (Integer)
: Current retry ID of this jobmessage (String)
: Message to loglevel (integer)
: Optional, verbose level
Response
Status: 200
{
"data": {},
"statusCode": 200
}