Skip to content

API Reference

NEMAR CLI communicates with the NEMAR API. This reference is for advanced users.

https://api.nemar.org

All authenticated endpoints require:

Authorization: Bearer nemar_your_api_key

nemar auth login and nemar auth signup drive this instead of a password (RFC 8628, the OAuth 2.0 Device Authorization Grant):

MethodEndpointWho calls itDescription
POST/auth/device/startCLIMint a device code and an 8-character user code
POST/auth/device/tokenCLIPoll for the API key once the code is confirmed
GET/auth/device/lookupBrowser (session)Read what a code names, before confirming or denying
POST/auth/device/confirmBrowser (session)Authorize the code; mints nothing itself, the key is minted only when the CLI collects it at /token
POST/auth/device/denyBrowser (session)Decline the code

POST /auth/device/token answers HTTP 400 with an error code the CLI’s poll loop switches on (authorization_pending, slow_down, and the three terminal codes expired_token, access_denied, invalid_grant). A terminal answer also carries reason, the more specific refusal code below:

{
"error": "expired_token",
"reason": "device_code_expired",
"message": "The code expired. Run `nemar auth login` again for a new one."
}
MethodEndpointDescription
GET/auth/keysList this account’s live keys
POST/auth/keysMint a named key (the paste-key fallback; refused for service/test accounts)
DELETE/auth/keys/:idRevoke a key by row id
DELETE/auth/keys/currentRevoke the key that authenticated this request (bearer credential only)

Every device-flow and key route above that refuses answers { "error": <code>, "message": <sentence> }:

CodeHTTPMeans
device_code_unknown404That code was not found.
device_code_expired410The code’s 10-minute window passed.
device_code_used409That code has already been used.
device_code_denied409The sign-in was declined in the browser.
account_pending403The account’s email is not verified yet.
account_revoked403The account’s access has been revoked.
identity_conflict403The account shares an identifier with another NEMAR account.
service_account403This is a service or test account; it cannot sign in this way. An owner mints its keys with nemar admin keys create.
person_account403This account belongs to a person; only POST /admin/users/:username/keys refuses this way, since a person mints their own keys instead.
too_many_keys409The account already holds the maximum of 25 live keys.
key_not_found404That key was not found, or is already revoked.
MethodEndpointDescription
POST/auth/loginValidate an API key (used by nemar auth login --key; not deprecated)
POST/auth/signupRegister a new user with a password (deprecated)
POST/auth/resend-verificationResend email verification
POST/auth/retrieve-keyRetrieve API key by email + password (deprecated)
POST/auth/request-key-regenerationRequest key regeneration (deprecated)
GET/auth/confirm-key-regenerationConfirm key regeneration (deprecated)
MethodEndpointDescription
GET/users/meGet current authenticated user (Bearer token)
GET/users/me/datasetsList the current user’s datasets
MethodEndpointDescription
GET/datasetsList datasets
GET/datasets/searchFull-text and semantic dataset search (?q=)
GET/datasets/resolve/:sourceIdResolve a source ID (e.g. OpenNeuro accession) to a NEMAR dataset
GET/datasets/:idGet dataset details
POST/datasetsCreate dataset
POST/datasets/:id/upload-urlsGet presigned URLs for direct file upload
POST/datasets/:id/upload-credentialsGet temporary S3 credentials for upload
POST/datasets/:id/download-credentialsGet temporary S3 credentials for download
GET/datasets/:id/manifestGet the latest version manifest
GET/datasets/:id/versionsList dataset versions
POST/datasets/:id/publish/requestRequest publication of a dataset
GET/datasets/:id/publish/statusCheck publication request status
MethodEndpointDescription
GET/sandbox/statusCheck sandbox training status
POST/sandbox/completeMark sandbox training complete
POST/sandbox/resetReset sandbox training
MethodEndpointDescription
GET/admin/usersList users (statuses, tiers, roles, kinds, and open upload-access requests)
GET/admin/users/:usernameGet a single user
POST/admin/approve/:usernameGrant upload access to a verified user
POST/admin/revoke/:usernameRevoke a user’s access
POST/admin/users/:username/kindChange a user’s account kind: person, service, or test (owner only)
POST/admin/users/:username/keysMint a key for a service/test account (owner only; refused for a person target)
GET/admin/users/:username/keysList a target account’s live keys (owner only; any kind)
DELETE/admin/users/:username/keys/:idRevoke one of a target account’s keys (owner only; any kind)
GET/admin/datasets/:id/doiGet DOI info for a dataset
POST/admin/datasets/:id/doi/conceptCreate concept DOI
POST/admin/datasets/:id/doi/updateUpdate DOI metadata
GET/admin/publish/requestsList publication requests
POST/admin/publish/:id/approveApprove and publish a dataset
POST/admin/publish/:id/denyDeny a publication request
DELETE/admin/datasets/:idDelete a dataset and all its resources
{
"error": "Error message",
"details": ["Additional information"]
}
CodeMeaning
200Success
400Bad request
401Unauthorized
403Forbidden
404Not found
409Conflict (a device code already used or denied, or a key/kind change raced another request)
410Gone (a device code’s window expired)
500Server error