On this page
Simple API server
Deno makes it easy to build lightweight, standards-based HTTP APIs using justthe Web Platform primitives (Request, Response, fetch) with built‑in datastorage in KV. In this tutorial you'll build and deploy a small link shortenerbacked by Deno KV, then push it to production on Deno Deploy.
We'll implement a simple link shortener service usingDeno KV. The modern Deno runtime providesDeno.serve()
which starts an HTTP server with zero configuration.
Create a local API serverJump to heading
Make a new directory for your project and rundeno init
to create a basic Denoproject.
Update themain.ts
file with the following code:
const kv=await Deno.openKv();interfaceCreateLinkBody{ slug:string; url:string;}functionjson(body:unknown, init: ResponseInit={}){const headers=newHeaders(init.headers); headers.set("content-type","application/json; charset=utf-8");returnnewResponse(JSON.stringify(body),{...init, headers});}functionisValidSlug(slug:string){return/^[a-zA-Z0-9-_]{1,40}$/.test(slug);}exportfunctionhandler(req: Request):Promise<Response>| Response{return(async()=>{// Basic CORS support (optional – remove if not needed)if(req.method==="OPTIONS"){returnnewResponse(null,{ headers:{"access-control-allow-origin":"*","access-control-allow-methods":"GET,POST,OPTIONS","access-control-allow-headers":"content-type",},});}if(req.method==="POST"){let body: CreateLinkBody;try{ body=await req.json();}catch{returnjson({ error:"Invalid JSON body"},{ status:400});}const{ slug, url}= body;if(!slug||!url){returnjson({ error:"'slug' and 'url' are required"},{ status:400,});}if(!isValidSlug(slug)){returnjson({ error:"Invalid slug format"},{ status:422});}try{newURL(url);}catch{returnjson({ error:"'url' must be an absolute URL"},{ status:422,});}// Prevent overwriting an existing slug using an atomic checkconst key=["links", slug];const txResult=await kv.atomic().check({ key, versionstamp:null}).set( key, url,).commit();if(!txResult.ok){returnjson({ error:"Slug already exists"},{ status:409});}returnjson({ slug, url},{ status:201});}// Redirect short links – extract slug from pathnameconst slug=newURL(req.url).pathname.slice(1);// remove leading '/'if(!slug){returnjson({ message:"Provide a slug in the path or POST to create one.",},{ status:400});}const result=await kv.get<[string]|string>(["links", slug]);const target= result.valueasstring|null;if(!target){returnjson({ error:"Slug not found"},{ status:404});}return Response.redirect(target,301);})();}exportfunctionstartServer(port=8000){return Deno.serve({ port}, handler);}startServer();
Run and test your server locallyJump to heading
Update thedev
task in thedeno.json
file to allow network permissions andadd the--unstable-kv
flag to allow using Deno KV locally:
{"tasks":{"dev":"deno run --unstable-kv -N main.ts"}}
Now you can run your server with:
deno task dev
For rapid iteration you could grant all permissions (
-A
) instead of justnetwork (-N
), but we do not recommend this for production environments.
Test your API serverJump to heading
This server will respond to HTTPGET
andPOST
requests. ThePOST
handlerexpects to receive a JSON document in request the body withslug
andurl
properties. Theslug
is the short URL component, and theurl
is the full URLyou want to redirect to.
Here's an example of creating a short link with cURL (expects a 201 Createdresponse):
curl--header"Content-Type: application/json"\--request POST\--data'{"url":"https://docs.deno.com/","slug":"denodocs"}'\ http://localhost:8000/
In response, the server returns JSON describing the stored link:
{"slug":"denodocs","url":"https://docs.deno.com/"}
If you try to run the curl to create the same slug again you'll get a 409Conflict:
{"error":"Slug already exists"}
AGET
request to our server will take a URL slug as a path parameter, andredirect to the provided URL. You can visit this URL in the browser, or makeanother cURL request to see this in action!
curl-v http://localhost:8000/denodocs
Deploy your API serverJump to heading
::: Deno Deploy account required
You will need an account on Deno Deploy to complete this section. If you haven'talready,sign up for a free Deno Deploy account.
:::
Provision a KV database on Deno DeployJump to heading
First, we will 'provision' a KV database in Deno Deploy for our deployed app touse.
- VisitDeno Deploy and click on the "Databases"tab.
- Click the "+ Provision database" button.
- Click the "Provision" button to create a free KV database.
- Give your database an identifying slug, select a region and click "ProvisionDatabase".
Deploy your serverJump to heading
Deploy your server with the following command:
deno deploy
This will briefly redirect you to a browser to authenticate with your DenoDeploy account, once authenticated, return to your terminal.
- Select an organization (if you belong to more than one).
- Select 'Create a new application'.
- Return to the browser to see your new project and give it a name.
- Click "Create App".
- Once created, click on the "Timelines" menu item on the left side.
- Click "Manage" next to the Databases section.
- Find the KV database you created earlier and click "Assign".
- Select your newly created app.
- Click on the app name in the "Assignments" column to return to your app.
- Click on the recent deployment link (which will have failed because it hasno KV assigned).
- Click the "Retry Build" button to redeploy your app with the KV databaseassigned.
Once successfully built, in the "Overview" tab, you will see your ProductionURL, you can now use this with your curl commands to test your deployed API.
Test out your new link shortenerJump to heading
Without any additional configuration (Deno KV just works on Deploy), your appshould run the same as it did on your local machine.
You can add new links using thePOST
handler as you did before. Just replacethelocalhost
URL with your live production URL on Deno Deploy:
curl--header"Content-Type: application/json"\--request POST\--data'{"url":"https://docs.deno.com/runtime/","slug":"denodocs"}'\ https://your-project.yourusername.deno.net/
Similarly, you can visit your shortened URLs in the browser, or view theredirect coming back with a cURL command:
curl-v https://your-project.yourusername.deno.net/denodocs
🦕 Now you know how to make a basic API with Deno and how to deploy it to DenoDeploy. Now that you have a working url shortener, you could consider making afrontend for it to allow users to create and manage their short links. Take alook at our (webframeworks)/frameworks page for someideas on how to get started!