Main content
Typical Workflow
Menu
Table of Contents
Overview
The API is designed so that you start from a base, find the resource you are interested in using, and gather relationships and attributes from those resources. By and large, you shouldn't construct URLs yourself, because sometimes those URLs may change. Top-level collections (nodes, users, registrations, files) and the detail views of each of those lists will be fine, but anything past that you want to get from the relationships of those resources.
A typical example is that you want to create a node, then add a file into the OSF Storage provider of that node. To do that, you:
- POST to the /nodes/ resource;
- Get the response back including the ID and relationships;
- Follow the files relationship to get the storage providers attached to that node;
- Find OSF Storage in that list;
- Get the links object from the OSF Storage item
- Find the upload link
- Use that upload link URL and PUT a file into OSF Storage using that URL.
If you already have a link to a node, you can GET that node's serialization directly.
Step by Step
All right, let's take a look at these items in depth. These examples presume you have generated a token and are using token authentication for your requests.
1 - POST to /nodes/
curl example:
## 1. POST to the nodes resource
curl -X "POST" "https://api.osf.io/v2/nodes/" \
-H "Authorization: Bearer Thisisnotarealauthtoken " \
-H "Content-Type: application/vnd.api+json" \
-d "{\"data\":{\"type\":\"nodes\",\"attributes\":{\"title\":\"Typical workflow example\",\"description\":\"This is a node created as an example of how to create a node and upload a file to that node\",\"public\":false,\"category\":\"project\"}}}"
2 - Get the response back
You'll get something that looks like the following, though with a different id:
{
"data": {
"relationships": {
"files": {
"links": {
"related": {
"href": "https://api.osf.io/v2/nodes/d92en/files/",
"meta": {}
}
}
},
"view_only_links": {
"links": {
"related": {
"href": "https://api.osf.io/v2/nodes/d92en/view_only_links/",
"meta": {}
}
}
},
"citation": {
"links": {
"related": {
"href": "https://api.osf.io/v2/nodes/d92en/citation/",
"meta": {}
}
}
},
"draft_registrations": {
"links": {
"related": {
"href": "https://api.osf.io/v2/nodes/d92en/draft_registrations/",
"meta": {}
}
}
},
"contributors": {
"links": {
"related": {
"href": "https://api.osf.io/v2/nodes/d92en/contributors/",
"meta": {}
}
}
},
"forks": {
"links": {
"related": {
"href": "https://api.osf.io/v2/nodes/d92en/forks/",
"meta": {}
}
}
},
"root": {
"links": {
"related": {
"href": "https://api.osf.io/v2/nodes/d92en/",
"meta": {}
}
}
},
"identifiers": {
"links": {
"related": {
"href": "https://api.osf.io/v2/nodes/d92en/identifiers/",
"meta": {}
}
}
},
"comments": {
"links": {
"related": {
"href": "https://api.osf.io/v2/nodes/d92en/comments/?filter%5Btarget%5D=d92en",
"meta": {}
}
}
},
"registrations": {
"links": {
"related": {
"href": "https://api.osf.io/v2/nodes/d92en/registrations/",
"meta": {}
}
}
},
"node_links": {
"links": {
"related": {
"href": "https://api.osf.io/v2/nodes/d92en/node_links/",
"meta": {}
}
}
},
"linked_nodes": {
"links": {
"self": {
"href": "https://api.osf.io/v2/nodes/d92en/relationships/linked_nodes/",
"meta": {}
},
"related": {
"href": "https://api.osf.io/v2/nodes/d92en/linked_nodes/",
"meta": {}
}
}
},
"wikis": {
"links": {
"related": {
"href": "https://api.osf.io/v2/nodes/d92en/wikis/",
"meta": {}
}
}
},
"affiliated_institutions": {
"links": {
"self": {
"href": "https://api.osf.io/v2/nodes/d92en/relationships/institutions/",
"meta": {}
},
"related": {
"href": "https://api.osf.io/v2/nodes/d92en/institutions/",
"meta": {}
}
}
},
"children": {
"links": {
"related": {
"href": "https://api.osf.io/v2/nodes/d92en/children/",
"meta": {}
}
}
},
"preprints": {
"links": {
"related": {
"href": "https://api.osf.io/v2/nodes/d92en/preprints/",
"meta": {}
}
}
},
"logs": {
"links": {
"related": {
"href": "https://api.osf.io/v2/nodes/d92en/logs/",
"meta": {}
}
}
}
},
"links": {
"self": "https://api.osf.io/v2/nodes/d92en/",
"html": "https://osf.io/d92en/"
},
"attributes": {
"category": "project",
"fork": false,
"preprint": false,
"description": "This is a node created as an example of how to create a node and upload a file to that node",
"current_user_permissions": [
"read",
"write",
"admin"
],
"date_modified": "2017-01-06T20:45:36.884977",
"title": "Typical workflow example",
"collection": false,
"registration": false,
"date_created": "2017-01-06T20:45:36.884977",
"current_user_can_comment": true,
"node_license": null,
"public": false,
"tags": []
},
"type": "nodes",
"id": "d92en"
}
}
3 - Follow the files relationship
So in all of that, you'll find a section called relationships, and in there, you'll find:
"files": {
"links": {
"related": {
"href": "https://api.osf.io/v2/nodes/d92en/files/",
"meta": {}
}
}
}
Since the href
for the files relationship is https://api.osf.io/v2/nodes/s6c68/files/
, so a GET on that:
## Request (2)
curl -X "GET" "https://api.osf.io/v2/nodes/d92en/files/" \
-H "Authorization: Bearer Thisisnotarealauthtoken" \
-H "Content-Type: application/vnd.api+json"
4 - Find OSF Storage in that list
In this example, there should really only be one item in the list, but if you were trying to get a storage provider off an existing node that had some storage addons connected, then you would have to search through to find the OSF Storage object.
{
"relationships": {
"files": {
"links": {
"related": {
"href": "https://api.osf.io/v2/nodes/d92en/files/osfstorage/",
"meta": {}
}
}
}
},
"links": {
"storage_addons": "https://api.osf.io/v2/addons/?filter%5Bcategories%5D=storage",
"upload": "https://files.osf.io/v1/resources/d92en/providers/osfstorage/",
"new_folder": "https://files.osf.io/v1/resources/d92en/providers/osfstorage/?kind=folder"
},
"attributes": {
"node": "d92en",
"path": "/",
"kind": "folder",
"name": "osfstorage",
"provider": "osfstorage"
},
"type": "files",
"id": "d92en:osfstorage"
}
5 - Get the links object
The links object from the response above is:
"links": {
"storage_addons": "https://api.osf.io/v2/addons/?filter%5Bcategories%5D=storage",
"upload": "https://files.osf.io/v1/resources/d92en/providers/osfstorage/",
"new_folder": "https://files.osf.io/v1/resources/d92en/providers/osfstorage/?kind=folder"
}
6 - Find the upload link
The upload link is:
https://files.osf.io/v1/resources/d92en/providers/osfstorage/
7 - Use that upload link URL to upload the file
The documentation for the file routes says that uploads require query parameters for the kind (file) and the file name.
Method: PUT
URL: /links/upload
Query Params: ?kind=file&name={new_file_name}
Body (Raw): <file data (not form-encoded)>
Success: 201 Created + new file representation
So the request will look like:
## Request (3)
curl -X "PUT" "https://files.osf.io/v1/resources/d92en/providers/osfstorage/?kind=file&name=new_file.txt" \
-H "Authorization: Bearer Thisisnotarealauthtoken" \
-H "Content-Type: application/vnd.api+json" \
-d "This is the entirety of the contents of the file I am uploading. It could have been more, but for an example, a small file seems like a better idea."
And you'll get back metadata that looks something like:
{
"data": {
"attributes": {
"extra": {
"version": 1,
"checkout": null,
"downloads": 0,
"hashes": {
"sha256": "f2fcf341553b5467efb5877a729bd507cbbe6d47fcfb1bee11085ecb8051dbcc",
"md5": "c7b1b5105d37498bcb14cba7d99c73ad"
},
"guid": null
},
"kind": "file",
"path": "/5870052e6c613b01fdac5df8",
"modified_utc": "2017-01-06T20:59:26+00:00",
"etag": "16196b720fbf3157b40d52f98e5fa320a14ea1af91dac55fe6b31433a33494d0",
"resource": "d92en",
"created_utc": null,
"materialized": "/new_file.txt",
"name": "new_file.txt",
"size": 148,
"modified": "Fri, 06 Jan 2017 20:59:26 GMT",
"contentType": "application/octet-stream",
"provider": "osfstorage"
},
"links": {
"upload": "https://files.osf.io/v1/resources/d92en/providers/osfstorage/5870052e6c613b01fdac5df8?kind=file",
"move": "https://files.osf.io/v1/resources/d92en/providers/osfstorage/5870052e6c613b01fdac5df8",
"download": "https://files.osf.io/v1/resources/d92en/providers/osfstorage/5870052e6c613b01fdac5df8",
"delete": "https://files.osf.io/v1/resources/d92en/providers/osfstorage/5870052e6c613b01fdac5df8"
},
"id": "osfstorage/5870052e6c613b01fdac5df8",
"type": "files"
}
}
Page permissions have changed
Your browser should refresh shortly…
Renaming wiki...
Wiki page deleted
Press Confirm to return to the project wiki home page.
Connected to the collaborative wiki
This page is currently connected to the collaborative wiki. All edits made will be visible to contributors with write permission in real time. Changes will be stored but not published until you click the "Save" button.
Connecting to the collaborative wiki
This page is currently attempting to connect to the collaborative wiki. You may continue to make edits. Changes will not be saved until you press the "Save" button.
Collaborative wiki is unavailable
The collaborative wiki is currently unavailable. You may continue to make edits. Changes will not be saved until you press the "Save" button.
Browser unsupported
Your browser does not support collaborative editing. You may continue to make edits. Changes will not be saved until you press the "Save" button.

Start managing your projects on the OSF today.
Free and easy to use, the Open Science Framework supports the entire research lifecycle: planning, execution, reporting, archiving, and discovery.
Copyright © 2011-2025
Center for Open Science
|
Terms of Use
|
Privacy Policy
|
Status
|
API
TOP Guidelines
|
Reproducibility Project: Psychology
|
Reproducibility Project: Cancer Biology