# What is it and how it's different

{% hint style="danger" %}
This API runs outside of Uploadcare's infrastructure. In order to provide full functionality, it **stores secret keys on the server**. If you want to play with it, create a new Uploadcare project, secret key, and remove this project after.
{% endhint %}

## What is it?

This is a proposal of how Uploadcare API v1 could look like. It's main goal to be modern and simple to use. It's not only documentation, it actually runs on Alex Gusev's server with [source code](https://github.com/alxgsv/uc) available, so you can play with it. Every endpoint documentation gives you a curl code to run in your terminal. Sometimes these codes contain variables:

* PROJECT\_ID or project\_id is a pubkey of your Uploadcare project
* SECRET\_KEY is a secret key of your Uploadcare project

The goal of this exercise was to ensure that proposed changes are not only possible to implement, but also possible to implement outside of Uploadcare's infrastructure.

## How it's different&#x20;

* It's a **REST** **API for the whole Uploadcare**. As a user, I don't want to deal with different API's with different references with different authentication models. It's just file handling, it shouldn't be that complex to create and process files.
* There are only two ways to create a File: upload it by calling `POST /api/v1/projects/:project_id/files.json` (this method handles direct, from\_url and s3 uploads) or use one of Conversions to create File from another File.
* When you want to create File or Group, it always immediately returns you a File or a Group, even if they're not ready. No more `from_url` tokens, add-on's `request_ids`.
* In order to do that, it gives own ids to Files (like `f-lzuWWKZSOEu5WqkOXU61r4`) or Groups (`g-2llVtEp1usejjUvH71cARf`). Without altering Uploadcare API's logic this is the only way to provide consistent experiense for API user.
* Instead of Add-ons and Conversions there are:&#x20;
  * **Conversions** of Files (convert videos, images, etc) that return a new File and
  * **Actions** with Files (AI image recognition, etc) that return an Action Result
* Therefore, remove\_bg is now considered a **Conversion.** Other Add-ons became Actions.
* When something can happen in background (File creation, Group creation, Action or Conversion), there will always be a webhook that notifies about progress
* It has CDN endpoints in order to handle delivery of new ids for Files and Groups:
  * `GET /cdn/f-lzuWWKZSOEu5WqkOXU61r4/-/preview/500x500/` will redirect to corresponding Uploadcare File UUID `https://ucarecdn.com/d05cbc92-99b5-40ef-80d3-70d74fdb6e77/-/preview/500x500/`
  * `GET /cdn/g-2llVtEp1usejjUvH71cARf/nth/0/` will redirect to corresponding Uploadcare Group UUID `https://ucarecdn.com/b37fc691-2ce3-44cc-ab08-00c170bbdb28/nth/0/`
* Every list is paginated with no exceptions: Files in Groups (to handle Groups with large amount of Files), Webhooks. There is always a temptation to not paginate something initially not considered big, and it can require API changes in the future.
* All times are in UTC in ISO 8601. Example: `2023-11-12T10:38:24.986Z`
* All responses correspond to [JSON:API](https://jsonapi.org/format/) format, including Errors
* Changes to `/v1` API must not break any existing v1 Clients. In case of breaking changes, `/v2` will be introduced
* Endpoint URL's follow common REST principles. For example:
  * `POST /api/v1/projects/:project_id/files.json` instead of \
    `POST /base` for direct upload and other endpoints for other uploads
  * `DELETE /api/v1/projects/:project_id/files/:file_id.json` instead of\
    `DELETE /files/{uuid}/storage/` to delete a file
* There is no need to add trailing slashes to endpoint URLs (because there are no endpoints that can possibly end with a slash)

### Security

Goal of this API is to be **secure by default**.&#x20;

**Currently at Uploadcare:**

* By default, if you know UUID of the File and project's public key, you have access to image metadata (including geo position of the image) via Upload API. There is no easy way to protect this data.
* By default, if you know UUID of the File, you have an access to original file, containing metadata, via CDN API.

There are a lot of scenarios how bad actors can benefit from it. From scanning internet for ucarecdn.com links, to targeting specific project with known project's public keys.

**In this proposal:**

* Only two roles have access to file's metadata via API:
  * Project owner via Bearer token
  * File/Group creator via Single Resource Token
* There is a `file[original_protected]` attribute of the File, that is true by default. It's impossible to get original File, if this set to true. All of the variations does not contain metadata in such case. `GET /cdn/${FILE_ID}` will return 404 for protected File, if called without authentication.

### Authentication

* It uses Bearer token authentication without request signatures. For clarity of demonstration, it uses Uploadcare's Secret keys as Bearer tokens.&#x20;
* For clarity of demonstration, it **stores Secret keys on server**, so please revoke your Secret keys after using them.
* It preserves ability to create Files and Groups **without** **Secret key**, but it doesn't give out all the file metadata to the whole Internet, like Upload API.
* In order to do that, every File and Group are assigned Single Resource Token. So, if I'm an End User who uploads a File to our Customer's project, I will receive Single Resource Token to make manipulations with this File or Group, but no other End User can see and manipulate it.

### Files

* Storing logic is replaced with Expiry logic. When creating a File, you can specify when to remove it with `expires_at` attribute. By default, Files does not expire. You can update or remove `expires_at` at any time before removal.
* `appdata` is no longer a part of the File structure, it moved to Action Results.
* There 2 ways to manipulate `metadata`. Pass an Object of new `metadata` to rewrite it completely, or pass an Array like `[{"key": key, "value": "value"}, ...]` to set only specific keys.
* No more usage of "Multipart" term to describe part-by-part file upload, because this term conflicts with more default [HTTP Multipart](https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html), that is actually the opposite: sending multiple parts of data in a *single* request. Instead, it's called Chunked upload.

### Groups

* Since Groups can hold unlimited number of Files, it is created in background, not on the fly.
* You can update Group. Under the hood it will create a new Group in Uploadcare, but Group id here will persist and you'll still be able to address by `GET /cdn/:group_id/...`
* To list files, user should use paginated `GET /api/v1/projects/:project_id/groups/:group_id/files.json`

### Conversions

* Always immediately return result File, even if it's not ready.
* There are 4 types of conversions: `video`, `image`, `document`, and `remove_bg`.
* All conversions are using `recipe` which conforms to Uploadcare's great URL API
* For example, for `remove_bg` you can pass such a `recipe`: `/position/original/-/add_shadow/true`.
* `image` is a new conversion. Under the hood it applies `recipe` to Uploadcare URL API and creates a File with from\_url.
* `remove_bg` became a Conversion, because it is a Conversion in terms of this API.

### Actions

* Every Action has it's own URL that you can POST to start Action, or GET to receive Action Result.

### Webhooks

* One webhook can handle multiple events, not only one.
* You GET, PATCH and DELETE webhooks only by their IDs (you DELETE them by `target_url` currenly).
* Signing secret is generated automatically for all webhooks.
* Webhooks events are:
  * For Files: "file.created", "file.updated", "file.deleted" (and Conversion status is basically a new resulting File status)
  * For Groups: "group.created", "group.updated", "group.deleted"
  * For Actions: "action.created", "action.updated" (so you receive a webhook when action is ready)
* Under the hook this project creates webhooks for all of Uploadcare webhook events, receives them, transforms, and delivers to end user's `target_url`.

### Things that are still not in the best shape

* Groups. They have potential to become more powerful tool and compare Collection functionality with Folder functionality.
* It feels like `thumbnal_group_uuid` for video files should actually be a Conversion. So you can convert video to thumbnails based on settings. Every video can potentially have different set of thubmbnails with different setting.
