{"id":18646342,"url":"https://github.com/dspace/restcontract","last_synced_at":"2025-07-20T11:33:32.058Z","repository":{"id":37087207,"uuid":"82175129","full_name":"DSpace/RestContract","owner":"DSpace","description":"REST Contract for DSpace 7–9","archived":false,"fork":false,"pushed_at":"2025-07-14T21:41:44.000Z","size":984,"stargazers_count":51,"open_issues_count":15,"forks_count":49,"subscribers_count":32,"default_branch":"main","last_synced_at":"2025-07-14T23:52:17.775Z","etag":null,"topics":["dspace","rest","rest-api"],"latest_commit_sha":null,"homepage":"https://wiki.lyrasis.org/display/DSDOC9x/","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DSpace.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-02-16T11:48:35.000Z","updated_at":"2025-07-08T01:25:24.000Z","dependencies_parsed_at":"2023-10-01T05:00:52.723Z","dependency_job_id":"9fa1f52d-0ad1-402c-b903-f5d670e90301","html_url":"https://github.com/DSpace/RestContract","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/DSpace/RestContract","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DSpace%2FRestContract","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DSpace%2FRestContract/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DSpace%2FRestContract/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DSpace%2FRestContract/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DSpace","download_url":"https://codeload.github.com/DSpace/RestContract/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DSpace%2FRestContract/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266117842,"owners_count":23879126,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dspace","rest","rest-api"],"created_at":"2024-11-07T06:19:20.765Z","updated_at":"2025-07-20T11:33:32.029Z","avatar_url":"https://github.com/DSpace.png","language":null,"readme":"# DSpace 7 REST Contract\n\nThis repository documents new DSpace REST API Contract beginning with version 7.0.\n* The code that implements this contract is on the  [`main` branch](https://github.com/DSpace/DSpace/tree/main/dspace-server-webapp) of the DSpace backend.\n* One example client which utilizes this contract is the [DSpace User Interface](https://github.com/DSpace/dspace-angular/), built in [Angular.io](https://angular.io/).\n\n## Table of Contents\n* [REST Endpoints](#rest-endpoints)\n* [Use of HTTP Verbs and Response Codes](#use-of-http-verbs-and-response-codes)\n    * [On Collection of Resource Endpoints](#on-collection-of-resources-endpoints)\n    * [On Single Resource Endpoints](#on-single-resource-endpoints)\n    * [On Sub-Path of a Single Resource Endpoint (Associations)](#on-sub-path-of-a-single-resource-endpoint-associations)\n    * [Error Codes](#error-codes)\n* [Pagination](#pagination)\n    * [Pagination Request Parameters](#pagination-request-parameters)\n    * [Pagination Response](#pagination-response)\n    * [Out of Bound Pages](#out-of-bound-pages)\n    * [Pagination Error Codes](#pagination-error-codes)\n* [REST Design Principles](#rest-design-principles)\n    * [On the Naming of Endpoints](#on-the-naming-of-endpoints)\n    * [HATEOAS \u0026 HAL](#hateoas--hal)\n    * [Statelessness](#statelessness)\n        * [JSON Web Tokens](#json-web-tokens)\n    * [ALPS](#alps---application-level-profile-semantics)\n    * [Spring Technology Alignment](#spring-technology-alignment)\n* [Content Negotiation](#content-negotiation)\n    * [Language Support](#language-support)\n* [Proxies](#proxies)\n* [ETags \u0026 Conditional Headers](#etags--conditional-headers)\n* [API Versioning](#api-versioning)\n* [Community Resources](#community-resources)\n\n## REST Endpoints\nAt the ROOT of the API a HAL document lists all the primary endpoints allowing full discovery of the API.\n* [Endpoints](endpoints.md) - Documentation for all available endpoints\n* [Submission / Deposit](submission.md) - How to deposit (or submit) a new Item into DSpace.\n* [Search Options and Relationships (on Endpoints)](search-rels.md) - How to use `/search` sub-paths on many endpoints\n* [Projections (on Endpoints)](projections.md) - How to use projections to return a subset or custom view of content\n* [CSRF Protection (on Endpoints)](csrf-tokens.md) - When using modifying verbs (POST, PUT, PATCH, DELETE), you *must* pass a CSRF token in the request.\n\n## Use of HTTP Verbs and Response Codes\n\n_Please note that within this section, all terms used are meant to reference RESTful terminology and/or terminology borrowed from [Spring Data REST](https://docs.spring.io/spring-data/rest/docs/current/reference/html/#repository-resources)._ \n - `resource` - anything that can be identified via a URI. It's a representation of an underlying object. e.g. `/items/123-456-789` is a resource that represents a single DSpace Item object. For additional examples see https://restful-api-design.readthedocs.io/en/latest/resources.html\n - `object` - we use this term to mean the actual object *behind* the resource. In other words, a resource is a JSON representation of some object (often a DSpaceObject) stored in the database. This is also sometimes called an \"entity\" in REST terminology.\n - `collection` - a group of resources e.g. `/items` is a collection of all DSpace Item resources. This is also sometimes called a \"collection resource\" (e.g. in Spring Data REST)\n     - Be aware that the term \"collection\" in this document has nothing to do with a DSpace Collection object. In REST terminology, a \"collection\" endpoint is simply an endpoint that returns multiple resources (objects), often in a paginated list.\n     - NOTE: Spring Data REST likes to use the phrase \"item resources\" for individual resources within a \"collection resource\". We've simplified this terminology and just call them \"resources\" and \"collections\", respectively.\n - `association` - a link or relationship between two resources. This is also sometimes called an \"association resource\" (e.g. in Spring Data REST).\n \n### On Collection of Resources Endpoints\n\nThis type of endpoint interacts with a group (or collection) of resources (objects). For example: `/api/core/items` references *all* Items in the system.\n\n- `POST` -\nCreates a new resource (object) and adds it to the group. Any required data (i.e. attributes) for the new object _must be included_ in the request body. An empty request body is not allowed, unless you are creating an empty object with no attributes.\n    - Related or additional information (such as required associations to other objects) may be passed as querystring parameters in the request, _if it is required to create the object._\n        ```\n        # For example, creating a Collection *requires* linking it to a parent Community\n        # In this scenario, we must have a querystring param to specify the parent Community UUID\n        curl -i -X POST \"http://localhost:8080/rest/api/core/collections?parent=\u003c:communityUUID\u003e\" \n            -H \"Content-Type:application/json\" \n            -d \"[{ ... attributes of new Collection ... }]\"\n        ```\n\n- `GET` -\nReturns the first page of the resources in the group (or collection). See [Pagination](#pagination) section. \n\n- `PATCH` -\n  Allows for batch updates (e.g. batch deletion via Patch 'remove' operation) to several resources in the collection at once.\n  The request body must adhere to the the [JSON Patch specification RFC6902](https://tools.ietf.org/html/rfc6902).\n  See [General rules for the Patch operation](patch.md) for more details.\n\n### On Single Resource Endpoints\n\nThis type of endpoint interacts with a single, existing resource (object). For example: `/api/core/items/\u003c:uuid\u003e` references a single Item resource.\n\n- `GET` -\nReturns a single resource.\n\n- `HEAD` -\nReturns whether the target resource is available.\n\n- `PUT` -\nReplaces the state of the target resource with the supplied request body. This updates the object (via full replacement). The updated information _must be included_ in the request body. An empty request body is not allowed, unless you are updating the object to be an empty object (with no attributes). Querystring parameters are not allowed, as `PUT` requests should always be performed on an existing object.\n\n- `PATCH` -\nSimilar to PUT but partially updating the resources state. We adhere to the [JSON Patch specification RFC6902](https://tools.ietf.org/html/rfc6902).\nSee [General rules for the Patch operation](patch.md) and [Modifying metadata via Patch](metadata-patch.md) for more details.\n\n- `DELETE` -\nDeletes the target resource (object).\n\n### On Sub-Path of a Single Resource Endpoint (Associations)\n\nThis type of endpoint interacts with (one or more) resources that are *associated with* a single resource. For that reason, it is sometimes called an \"association\" endpoint. For example: `/api/core/items/\u003c:uuid\u003e/mappedCollections` references all Collections that are mapped to a single Item resource.\n\n- `GET` -\nReturns the state of the association (for the current resource)\n\n- `PUT` -\nBinds (or links) the resource(s) pointed to by the given URI(s) to the current resource. This replaces any existing links with the URIs passed in the request. Resource URIs to link must be sent in the body of the request using `Content-Type:text/uri-list`. [See example from Spring Data REST Relationships](https://www.baeldung.com/spring-data-rest-relationships). Return `400 Bad Request` if multiple URIs were given for a *-to-one-association\n   ```\n   # Example curl command to replace Item-to-Collection mappings with the two listed\n   # Notice the two Collection URIs are separated by a newline (\\n)\n   curl -i -X PUT \"http://localhost:8080/rest/api/core/items/\u003c:uuid\u003e/mappedCollections\" \n        -H \"Content-Type:text/uri-list\" \n        -d \"http://localhost:8080/rest/api/core/collections/1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb \\n http://localhost:8080/rest/api/core/collections/5ad50035-ca22-4a4d-84ca-d5132f34f588\"\n   ```\n\n- `POST` -\nOnly supported for collection associations (i.e. associations allowing for multiple resources). Adds/Links a new resource (via its URI) to the association. Resource URIs to link must sent in the body of the request using `Content-Type:text/uri-list`. [See example from Spring Data REST Relationships](https://www.baeldung.com/spring-data-rest-relationships)\n   ```\n   # Example curl command to add a *new* Collection mapping for an Item\n   curl -i -X POST \"http://localhost:8080/rest/api/core/items/\u003c:uuid\u003e/mappedCollections\" \n        -H \"Content-Type:text/uri-list\" \n        -d \"http://localhost:8080/rest/api/core/collections/5ad50035-ca22-4a4d-84ca-d5132f34f588\"\n   ```\n\n- `DELETE` -\nUnbinds (unlinks) the association. Return `405 Method Not Allowed` if the association is required (and cannot be removed).  DELETE requests should _not_ contain a request body as some clients do not support sending a DELETE request with a body. Therefore, if an individual association needs to be removed, the DELETE request should reference that individual association in the URI of the request. For example:\n   ```\n   # Example curl command to delete a *single* Collection mapping for an Item\n   curl -i -X DELETE \"http://localhost:8080/rest/api/core/items/\u003c:uuid\u003e/mappedCollections/\u003c:collection_uuid\u003e\"\n   \n   # Example curl command to delete *ALL* Collection mappings for an item (unsupported at this time)\n   curl -i -X DELETE \"http://localhost:8080/rest/api/core/items/\u003c:uuid\u003e/mappedCollections\n   ```\n\n### Error Codes\n* `400 Bad Request` - if multiple URIs were given for a to-one-association\n* `401 Unauthorized` (Unauthenticated) - if the request requires a logged-in user\n* `403 Forbidden` - if the requester doesn't have enough privilege to execute the request, or the request requires [CSRF protection](csrf-tokens.md) and the CSRF token was missing or invalid.\n* `404 Not Found` - if the requested entity or collection doesn't exist\n* `405 Method Not Allowed` - if the method is not implemented, or a DELETE method is called on a non-optional association\n* `422 Unprocessable Entity` - if the request is well-formed, but is invalid based on the given data. For example, if you attempt to create a resource under a non-existent parent resource, or attempt to update a read-only (non-editable) field.\n\n## Pagination\nEach endpoint that exposes a collection of resources, including sub-paths for embedded or linked collections (aka list of items of a collection, etc.), MUST implement the pagination with the following common behavior\n\n### Pagination Request Parameters\n- `page` - zero-based integer value that specify the requested page in the result set (default 0). Negative values must be rejected with a `400` Error code.\n- `size` - the dimension of the result set window to show. It must be a positive value. Negative or zero values must be rejected with a `400` Error code. The default value as well as maximum values are configurable by the system administrator. Different Maximum values apply for anonymous users, logged-in users and administrators. Size over the maximum value are automatically reset to the maximum allowed value, no error is thrown.\n- `sort` - the criteria to use. Ordering is specified appending a comma and the keyword asc or desc to the criteria name (i.e. title,asc). Unknown sort criteria and/or ordering keyword produce an error response with Http Code `400`\n\n### Pagination Response\nThe HAL document always includes a page object with the following attributes\n- `size` - the dimension of the result set window returned (can be different from the requested value due to imposed limit, see the request parameters section)\n- `totalElements` - the total size of the result set\n- `totalPages` - the number of available page of result using the current window size\n- `number` - the index (zero-based) of the returned page\n\nAn example\n```\n\"page\": {\n    \"size\": 5,\n    \"totalElements\": 14,\n    \"totalPages\": 3,\n    \"number\": 0\n}\n```\nWhen applicable, the following links may also appear:\n- `self` - a parameterized link to the requested collection page\n- `next` - the link to the next page of resources in the collection, if any, keeping the same option for size and sorting\n- `previous` - the link to the previous page of resources in the collection, if any, keeping the same option for size and sorting\n- `first` - the link to the first page of resources in the collection, keeping the same option for size and sorting\n- `last` - the link to the last page of resources in the collection, keeping the same option for size and sorting\n\nAn example\n```\n\"_links\": {\n    \"first\": {\n      \t\"href\": \"http://localhost:8080/server/api/core/bitstreams?page=0\u0026size=5\"\n    },\n    \"self\": {\n      \t\"href\": \"http://localhost:8080/server/api/core/bitstreams\"\n    },\n    \"next\": {\n      \t\"href\": \"http://localhost:8080/server/api/core/bitstreams?page=1\u0026size=5\"\n    },\n    \"last\": {\n        \"href\": \"http://localhost:8080/server/api/core/bitstreams?page=2\u0026size=5\"\n    }\n}\n```\n\n### Out of Bound Pages\nIf the request parameters lead to a page outside the result set, then an empty page should be returned with the links needed to go to the first and last page of the result set (if the results set is not empty), and the total number of resources in the collection.\n\n### Pagination Error Codes\n`400 Bad Request` - If an unknown sort criteria is requested, or a not valid ordering keyword is specified\n\n## REST Design Principles\nIn the creation of the REST API, we've tried to follow a few specific design principles listed below\n\n### On the Naming of Endpoints\n\nWe strive to align with these rules for all REST API endpoint names:\n* Endpoint names MUST use plural nouns instead of verbs.\n* When compounds are used in an endpoint name, the words MUST be concatenated, all lowercase, without punctuation. For example: `metadatafields`, NOT `metadata-fields` or `MetadataFields` or `metadataFields`.\n* Endpoint names SHOULD be descriptive, but reasonably short (\u003c25 characters). Abbreviations are _not recommended_, unless necessary for brevity. When abbreviations are used, the REST Contract MUST spell out the meaning of the abbreviation.\n* Endpoints SHOULD be grouped with other related endpoints by category or name. \n    * The \"category\" is the first part of the endpoint's path and is always a singular noun. For example, all configuration-related endpoints use the category \"config\", which means they appear under `/api/config/*`.  Similarly, all submission-related endpoints use the category \"submission\", which means they appear under `/api/submission/*`.\n    * Alternatively, the name of the endpoint may include a prefix to relate it to other endpoints.  For example, all workflow related endpoints start with the prefix \"workflow\", regardless of their category. For example: `/api/config/workflowdefinitions`, `/api/config/workflowsteps`, `/api/workflow/workflowitems`.\n\n### HATEOAS \u0026 HAL\nThe REST API supports the [HATEOAS paradigm](https://restfulapi.net/hateoas/) and adopt the [HAL format](http://stateless.co/hal_specification.html) to express links and embedded resources. Links are always **absolute** to allow for easier implementation of \"follow link\" methods on the REST client side.\n\nBecause the API responds using the HAL Format, we distribute it with an [embedded HAL Browser provided by Spring](https://docs.spring.io/spring-data/rest/docs/current/reference/html/#_the_hal_browser).\n\n### Statelessness\nThe REST API is [stateless](https://restfulapi.net/statelessness/), meaning the client is responsible for keeping state information and sending it to the server when it is necessary. Because the server stores no state (or session) information internally, it will return a \"token\" (which contains any state information) to the client. The client must return that token in *each subsequent request*, if the client wants that state information preserved.\n\n#### JSON Web Tokens\n[JSON Web Tokens (JWT)](https://jwt.io/) are used to store state (and authentication) information between requests. This is the format of token the REST API returns to the client. The client should return the JWT to the server in subsequent requests.\n\n### ALPS - Application Level Profile Semantics\n**While not yet implemented**, we expect future support for the ALPS metadata (\u003chttp://alps.io/\u003e), so a profile link MUST exist from the root of API.\nA profile link as defined in [RFC 6906](\u003chttps://tools.ietf.org/html/rfc6906\u003e), is a place to include application level details. See the ALPS draft spec (http://tools.ietf.org/html/draft-amundsen-richardson-foster-alps-00)\n\n### Spring Technology Alignment\nWhile it's an implementation detail, the new REST API uses many Spring REST (Java) libraries, including:\n\n* [Spring Boot](https://spring.io/projects/spring-boot) - Provides base Spring webapp functionality\n* [Spring MVC](https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/web.html#mvc) - Provides Spring web framework\n* [Spring REST](https://spring.io/understanding/REST) - Provides base REST tools/libraries for building REST APIs on Spring MVC\n* [Spring HATEOAS](https://spring.io/projects/spring-hateoas) - Provides tools to create REST APIs following HATEOAS principles, and returning HAL Format responses.\n* [Spring Data REST](https://spring.io/projects/spring-data-rest) (_alignment_) - We do **NOT** directly use Spring Data REST at this time (because of incompatibilities with our data layer). However, we have chosen to _align our implementation with Spring Data REST_ where possible.\n* [Spring Data REST Hal Browser](https://docs.spring.io/spring-data/rest/docs/current/reference/html/#_the_hal_browser) - Provides the out-of-the-box HAL Browser you see when accessing our REST API\n* [Spring REST Docs](https://spring.io/projects/spring-restdocs) - Provides tools to help document REST APIs in Spring MVC\n\nEach of these libraries were chosen based on design principles above, and based on the fact that much of our underlying Java APIs use or align with Spring technologies.\n\n## Content Negotiation\nThe DSpace REST API only supports the `application/json` response format at this time. So, there is no real content negotiation according to the broad meaning of the term.\n\nNevertheless, some concepts of content negotiation still apply.\n* `POST` requests may accept a `content-type` other than `application/json` in order to drive the creation of the resource. For example, `text/uri-list` and `multipart/form-data` may be supported.\n* `PUT` requests on the association endpoint accept `text/uri-list` according to Spring Data best practices.\n\n### Language Support\nWhile most i18n (internationalization) settings exist in the UI layer, there are some backend features which also require i18n, such as Submission forms, Controlled Vocabularies, and Authorities.\n\nFor such features the `Accept-Language` header may be used by the REST client to force the use of a specific locale, if supported by the DSpace instance and endpoint in the response. (Please note that not all the DSpace instances support multiple locales. This can be discovered by querying the configuration endpoint for the `webui.supported.locales` key.)\n\nIf the support for multiple locales is enabled in the DSpace instance, a request with an `Accept-Language` header is expected to be processed as follows:\n* If none of the requested locales is supported, the server will ignore the header. This provides more user-friendly behavior when browsing the REST API via a browser (see https://tools.ietf.org/html/rfc7231#section-5.3.5)\n* If at least one acceptable locale is requested, the server will use the one with the higher priority in the `Accept-Language` header to process the request\n* If the requested endpoint is configured to respond differently based on the selected locale, then the `Content-Language` response header will detail which locale was used to generate the response.\n* If the requested endpoint responds the same no matter which locale is requested, then the `Content-Language` response will return the list of all supported locales.\n    * This also implies that the ROOT endpoint will return the list of supported locales via the `Content-Language` response header\n\nThe REST client is expected to use the `Content-Language` Response Header as part of their caching strategy.\n\nPlease note that a REST client MUST always send the `Accept-Language` header for all the subsequent requests _after_ a user has chosen a preferred language/locale.\n\nIf no explicit locale is requested by the client, or the requested locale is not supported, then DSpace will check if the current user is authenticated and has a preferred language stored (if any).  If so, DSpace will respond in the preferred locale. If not (or if the user is not authenticated), DSpace will respond with the configured default locale (configuration key `default.locale`) as a fallback.\n\n## Proxies\nThe DSpace REST API supports the `X-Forwarded-For` header by default for all requests coming from localhost (127.0.0.1). This allows any clients running on the same server to immediately proxy requests for other IP addresses.\n\nIf your client (or User Interface) is on a different server, you may add additional \"trusted\" IP addresses (or ranges) which are allowed to use the `X-Forwarded-For` header. To do so, modify the `proxies.trusted.ipranges` setting in your `local.cfg`. This configuration accepts a comma-separated list of IPs and/or you may specify a range by listing the first three blocks of the IP range (e.g. 123.45.67)\n\nKeep in mind, the `X-Forwarded-For` header is ONLY read if `useProxies=true` (default value) is also set in your DSpace configuration (either `dspace.cfg` or `local.cfg`).\n\n## ETags \u0026 conditional headers\nThe ETag header (\u003chttp://tools.ietf.org/html/rfc7232#section-2.3\u003e) provides a way to tag resources. This can prevent clients from overriding each other while also making it possible to reduce unnecessary calls. It is expected that all the returned document have an ETag\n\nThe ETag value can be used with in GET request with the *If-None-Match* conditional header. If the header MATCHES the ETag, the API will conclude nothing has changed, and instead of sending a copy of the resource, an HTTP 304 Not Modified status code is returned.\n\nThe ETag value can be also used with DELETE, POST, PUT and PATCH with the *If-Match* conditional header to avoid performing an action on changed resources (concurrency issues, optimistic lock approach).\n\nFinally, when possible the If-Modified-Since header in GET request should be respected. If the resource has been not modified since the value of the Header the API should return an\nHTTP 304 Not Modified status code. Resources that support the *If-Modified-Since* header *MUST* return the Last-Modified Header in the GET response. That header *MUST BE NOT* returned by resources not able to manage the If-Modified-Since header.\n\n## API Versioning\n\nAt this time, DSpace REST API is versioned alongside DSpace software (e.g. DSpace v7.x comes with REST API v7).\nPlease check the Release Notes for information around any deprecations / breaking changes to the API between major versions of DSpace.\n\n## Community Resources\n* [REST Code Branch](https://github.com/DSpace/DSpace/tree/main/dspace-server-webapp)\n* [REST Coding Tips](https://wiki.lyrasis.org/display/DSPACE/DSpace+7+REST:+Coding+DSpace+Objects)\n* [DSpace Community Slack](https://wiki.lyrasis.org/display/DSPACE/Slack) (See `#rest-api` channel)\n* [DSpace 7 Working Group](https://wiki.lyrasis.org/display/DSPACE/DSpace+7+Working+Group) - Includes weekly meeting agenda/notes and historical documentation behind the REST API\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdspace%2Frestcontract","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdspace%2Frestcontract","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdspace%2Frestcontract/lists"}