# Create links from your server or app

Besides the console, you can create links over Mocco's API. Your server manages links with a **secret** key, and your app makes share links (for a "share this item" button) with a **publishable** key.

Links need the same setup as in the console first: Deep links turned on, a link host chosen and an iOS or Android app registered (see [Deep links overview](https://www.mocco.club/docs/en/articles/xz8btr-overview)).

## 1. Create a key

Owners and admins create keys under **API keys** in the project.

- For your server, create a **Secret** key with `links:write` to create and change links, and `links:read` to read them and their clicks. Keep it on the server; Mocco refuses a secret key sent from a browser.
- For your app, create a **Publishable** key with `links:app`. It can only create share links, so it is safe to ship in the app.

## 2. Create links from your server

With Node, use `@mocco/node`:

```ts
import { createMoccoServer } from '@mocco/node';

const mocco = createMoccoServer({ secretKey: process.env.MOCCO_SECRET_KEY! });

const link = await mocco.links.create({
  slug: 'spring',
  deepLinkPath: '/sale/spring',
  campaign: 'spring-2026',
  fallbacks: { web: 'https://shop.example.com/spring' },
  og: { title: 'Spring sale', description: 'Up to 50% off' },
});
console.log(link.url); // https://acme.<link domain>/spring
```

A secret key can set everything the console can: the slug, label, path, params, campaign, web fallbacks, share preview and expiry. Web fallbacks must be on one of your verified web destinations, as in the console. The same client lists links (`list`), reads one (`get`), changes one (`update`; the slug never changes), disables and enables it, and reads its clicks per day (`stats(id, { from, to })`).

From any other language, call the API directly with `Authorization: Bearer <secret key>`. Its description is at `/v1/links/openapi.json`.

Changes made with a secret key appear in the audit log as made by the person who created the key, naming the key.

## 3. Create share links from your app

With a publishable key, your app creates share links with only these fields:

- `deepLinkPath`: where the link opens in your app, such as `/items/42`
- `params` (optional): values your app receives with the link
- `campaign` (optional)
- `og.title` and `og.description` (optional): the share preview's texts

```ts
const response = await fetch('https://<your Mocco API>/v1/links', {
  method: 'POST',
  headers: { authorization: `Bearer ${publishableKey}`, 'content-type': 'application/json' },
  body: JSON.stringify({ deepLinkPath: '/items/42', og: { title: 'Item 42' } }),
});
const { url } = await response.json();
```

Mocco generates the slug, and people without your app go to its store page. A share link can't set a slug, a label, web fallbacks, an image or an expiry; Mocco answers `field_not_allowed` and names the field. That way a key someone copies out of your app can only make links into your own app.

**The same content gives the same link.** When your app asks again for a link with the same path, params, campaign and texts, Mocco answers the link it made before instead of a new one, so a share button doesn't make a link per tap.

**Limits.** One key can create 60 share links a minute, and a project's apps can create 5,000 new share links a day. Past either, Mocco answers `429` with `Retry-After`; asking again for a link that already exists still works.

Share links appear in the console's link list like any other. If one is abused, disable it there: your app then can't make that link again.
