What is it and how it's different

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 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

  • 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:

    • 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 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.

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.

  • 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, 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.

Last updated