.. Copyright (C) 2016-2025 SpaceKnow, Inc. ============= API Mechanics ============= .. _api.mechanics.authorization: ************* Authorization ************* .. only:: not holygrail Please contact `SpaceKnow`_ team to obtain an account. .. _SpaceKnow: https://spaceknow.com/support/ Making Authorized Request ========================= `JWT (JSON Web Tokens)`_ is used for authorization of every request against SpaceKnow APIs. JWT is sent in ``Authorization`` header after ``Bearer`` keyword (i.e. ``Authorization: Bearer JWT-TOKEN``). .. _JWT (JSON Web Tokens): https://jwt.io/ **Example of an authorized request**: .. http:post:: /imagery/search/initiate .. only:: not holygrail .. sourcecode:: http POST /imagery/search/initiate HTTP/1.1 Host: api.spaceknow.com Content-Type: application/json Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.t-IDcSemACt8x4iTMCda8Yhe3iZaWbvV5XKSTbuAn0M .. only:: holygrail .. sourcecode:: http POST /imagery/search/initiate HTTP/1.1 Host: api.local Content-Type: application/json Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.t-IDcSemACt8x4iTMCda8Yhe3iZaWbvV5XKSTbuAn0M .. sourcecode:: json { "provider": "gbdx", "dataset": "idaho-pansharpened", "extent": { "type": "Polygon", "coordinates": [[ [115.84512233734131, -31.96024562403475], [115.84490776062012, -31.96559774488045], [115.84851264953612, -31.965452113067933], [115.84842681884766, -31.96053690394404], [115.84512233734131, -31.96024562403475] ]] } } Get JWT ======= .. only:: not holygrail Obtaining JWT tokens by clients is currently only supported for Auth0 OIDC provider. Use `Auth0 Authentication API`_ to get a JWT. Tokens are valid for 10 hours. .. _Auth0 Authentication API: https://auth0.com/docs/api/info#authentication-api * SpaceKnow client ID: ``hmWJcfhRouDOaJK2L8asREMlMrv3jFE1`` * SpaceKnow Auth0 domain: ``spaceknow.auth0.com`` For example request for JWT in exchange for `email and password`_ looks like this: .. _email and password: https://auth0.com/docs/api/authentication?http#database-ad-ldap-active- .. http:post:: https://spaceknow.auth0.com/oauth/ro **Example request**: .. sourcecode:: http POST /oauth/ro HTTP/1.1 Content-Type: application/json .. sourcecode:: json { "client_id": "hmWJcfhRouDOaJK2L8asREMlMrv3jFE1", "username": "your_spaceknow_email@example.com", "password": "your_spaceknow_password", "connection": "Username-Password-Authentication", "grant_type": "password", "scope": "openid" } :>json string id_token: JWT to be later used in authorized API requests. **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json .. sourcecode:: json { "id_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.t-IDcSemACt8x4iTMCda8Yhe3iZaWbvV5XKSTbuAn0M", "access_token": "some-token", "token_type": "bearer" } To acquire a token in devel environment, fire the request above but change the following: * SpaceKnow client ID: ``UWBUvt919N0sUXjG1CepGhiR0DJuazSY`` * SpaceKnow Auth0 domain: ``https://spaceknow-test.auth0.com`` .. only:: holygrail Use `FusionAuth Authentication API`_ to get a JWT. Tokens are valid for 10 hours. .. _FusionAuth Authentication API: https://fusionauth.io/docs/v1/tech/oauth/#example-resource-owner-password-credentials-grant For example request for JWT in exchange for email and password looks like this: .. http:post:: http://fusionauth.local/oauth2/token **Example request**: .. sourcecode:: http POST /oauth2/token HTTP/1.1 Content-Type: application/x-www-form-urlencoded :formparam grant_type: always set to ``password`` for Resource Owner Password Credentials Grant :formparam username: your_holygrail_email@example.com :formparam password: your_holygrail_password :formparam scopes: always set to ``openid`` :formparam client_id: always set to ``8ed4ebd4-cd8b-4c46-ab81-8e8d7fda42a4`` :>json string access_token: JWT to be later used in authorized API requests. **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json .. sourcecode:: json { "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IkY2Vm9Kd1BaN1Jyc1BpVVJzdGVSVWFFeVZkOCJ9.eyJhdWQiOiI4ZWQ0ZWJkNC1jZDhiLTRjNDYtYWI4MS04ZThkN2ZkYTQyYTQiLCJleHAiOjE2MDA0NDIzMDcsImlhdCI6MTYwMDQzODcwNywiaXNzIjoiaG9seWdyYWlsLmxvY2FsIiwic3ViIjoiMDdjOGNhYTctMWJiZC00OTU2LWE3MWMtOWI1MjE3NmU5YjBlIiwianRpIjoiYmZhZjMzZDktNjAxOC00YmRjLThjMTctZTU4NzU1NjVhMWQ4IiwiYXV0aGVudGljYXRpb25UeXBlIjoiUEFTU1dPUkQiLCJlbWFpbCI6Imk5bi10ZXN0c0BzcGFjZWtub3cuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWV9.fgvHbYYxccCgjyUGOThQ7hXcEXO39z0amLKLJ-92miFU73WxfDpfcxAdBEcbMsvFM8MswGjqRA5yb4GAIgkY9rJ2VVdjWZ07i9qSeswakqcwRoZsH5WpB7IZ69HjXMSaGd7IXhPj_xWszcDAxr1Cdk4uPQOLLhSr7J-sTroQmn6F8u20_WoShIfNwomTeoOjVynCFX3H7dBdK3_U2ODHbUtu7Tnf4HDAklgLJu_XFSrfqR3MGbfuY2emcfhVuXDcIQ3b8SZ8DzpU2_KirbBpfhHsJm6Xj09l7pGbPbA1PK2FvdaYUWOBa4XLrdJGuS5yh3oPm9cMIkaLCw6l4gpas1trqgu8A-hqiUpvMCSCKH5tCDJDZLOSzG_Y0Fj_Ugs2T5zN30cah0Rx-uw7SEOJeObVdgjHI-9ve0HOcKhQQI5eVkv_XjdbdLEYd0I8LJUiuFayw1KhnVCm3V5VsC32ZlrqLQwMYp_jPwRquiCBzjjN6TuyQZ5h8i4fVnV3y8_F3EQdAJeRNby5fac4qddRlpaxOzL4OkibSCscCq-rL0H5vl62DWtHrdD1_JdvhycUJwaBqNBrRlojhtSvjCtxQTNx_gwJCvwcVrsupjdT4hh_avGJhWVtTAoUUt3cuZ1fTjngOmHx_WurkPr_Ru2EueiaoQ-VRu6DM18ZDDXj5BY", "expires_in": 3599, "token_type": "Bearer", "userId": "07c8caa7-1bbd-4956-a71c-9b52176e9b0e" } .. _api.mechanics.permissions: *********** Permissions *********** Most SpaceKnow API endpoints have a set of permissions required to access them. A permission is a string with ``.`` as a namespace separator, for example ``imagery.availability``. The following Python code snipped shows how permissions are tested. .. code-block:: python user_permission = user_permission_str.split('.') required_permission = required_permission_str.split('.') test_len = min(len(user_permission), len(required_permission)) user_permission_part = user_permission[:test_len] required_permission_part = required_permission[:test_len] return user_permission_part == required_permission_part See the following example, where columns are permissions of a user and rows required permission. +--------------------------------------------------+--------------------------+-------------------------------+------------+-------------+ | | ``imagery.availability`` | ``imagery.availability.gbdx`` | ``kraken`` | ``imagery`` | +--------------------------------------------------+--------------------------+-------------------------------+------------+-------------+ | ``imagery.availability`` | true | true | false | true | +--------------------------------------------------+--------------------------+-------------------------------+------------+-------------+ | ``imagery.availability.gbdx.idaho-pansharpened`` | true | true | false | true | +--------------------------------------------------+--------------------------+-------------------------------+------------+-------------+ | ``imagery.availability.pl`` | true | false | false | true | +--------------------------------------------------+--------------------------+-------------------------------+------------+-------------+ | ``imagery.images`` | false | false | false | true | +--------------------------------------------------+--------------------------+-------------------------------+------------+-------------+ | ``imagery`` | true | true | false | true | +--------------------------------------------------+--------------------------+-------------------------------+------------+-------------+ .. only:: not holygrail See also :ref:`api.user`. .. _api.mechanics.errors: ********** API Errors ********** The HTTP status code of ``5XX`` is returned if a server-side error occurs. The status code of ``4XX`` is returned if a client-side error occurs. **Error Response body**: .. code-block:: json { "error": "MACHINE-READABLE-ERROR-CODE", "errorMessage": "A human readable error description." } List of HTTP Status Codes ========================= * 400 - Bad Request. Make sure that the request body and headers are correct. * 401 - Unauthorized. You do not have sufficient rights or credits to perform this action. * 402 - Payment Required. Allocation is required prior to running this request. * 403 - Forbidden. You are trying to modify internal assets. * 404 - Not Found. You are trying to access resource which does not exist. * 405 - Method Not Allowed. Used HTTP method is not allowed for this endpoint. * 409 - Conflict. You are trying to modify resource which is in conflict with another. * 413 - Payload Too Large. Request payload is too large. * 422 - Unprocessable Content. Request payload did not pass validation. * 424 - Failed Dependency. This status code is returned when a failed processing pipeline is retrieved (see :ref:`Asynchronous API `). * 429 - Too Many Requests. Too many requests to this endpoint, please try again later. * 500 - Internal Server Error. * 503 - Service Unavailable. Try again later. List of Error Codes =================== See :ref:`API errors ` for details. ***************** Asynchronous APIs ***************** .. Define the anchor after the header to prevent it being swallowed by only. .. _api.mechanics.asynchronous: Processes, that can take from minutes to hours, are handled asynchronously in the "pipeline". All APIs that work asynchronously have ``../initiate`` and ``../retrieve`` endpoints. To trigger a new pipeline, use ``../initiate``. To check whether a pipeline is finished, request ``/check-status`` endpoint of :ref:`Tasking API `. To get a finished pipeline result, request ``../retrieve``. .. _api.mechanics.asynchronous.initiate: .. http:post:: /.../initiate :>json string pipelineId: ID of the processing pipeline. It will be used later to check pipeline status and to retrieve pipeline result. :>json string status: status of the pipeline at the time the response was generated. See :ref:`Tasking API ` to learn more about pipeline statuses. :>json int nextTry: recommended delay in seconds before first status check. See :ref:`Tasking API ` :>json str subGeometryId: This is only provided in Kraken Release initiate endpoint if ``subGeometry`` was present in the request. See :ref:`Release with subGeometry `. **Example response**: .. sourcecode:: json { "nextTry": 5, "pipelineId": "3g4PovfhGxmymQolpgvv", "status": "NEW" } **Example with subGeometryId response**: .. sourcecode:: json { "nextTry": 5, "pipelineId": "3g4PovfhGxmymQolpgvv", "status": "NEW", "subGeometryId": "0123456789abcdef" } Pipeline is stopped and set to the ``FAILED`` status if an error occurred during pipeline processing. Request on ``../retrieve`` for the failed pipeline is responded with a status code ``424``, and with a specific error code and message. See :ref:`api.mechanics.errors`. .. _api.mechanics.asynchronous.retrieve: .. http:post:: /.../retrieve :` APIs may be paginated. In the case of asynchronous APIs a new pipeline is started for every new requested page.