Browse docs REST API

REST API

Create links, Smart Links, forms and Multilink pages from your own code, and read their analytics, with the same rules as the Walink app.

Updated November 11, 2026 View as Markdown

The Walink API lets a script, a backend or any no-code tool that sends HTTP requests do what you do in the app. Every request runs through the app's own rules, so addresses, allowance and ownership are checked the same way, and every create makes a draft, except a free link, so nothing goes live by accident.

This page gets you to a first call. Every endpoint and field is in the full API reference, which also has a console to try requests.

What you can automate

Resource What the API does
Premium Links (/v1/links) List, create drafts, edit, publish, unpublish, delete, style the QR
Smart Links (/v1/smart-links) The same, with destinations and routing
Forms (/v1/forms) The same, plus the responses people sent
Multilink pages (/v1/multilinks) The same
Free links (/v1/free-links) List, create, read, delete
Analytics (/v1/analytics) Figures and breakdowns by country, source, device and more
Account (/v1/account) Profile, allowance in use, free links held

Any Walink account can use the API. Drafts are free. Publishing uses your subscription's allowance and analytics need a subscription, as in the app.

Create a token

  1. Sign in to Walink, open the account menu (the round button at the top right) and select Developers.
  2. Under API Tokens, select Create token.
  3. Give it a Name, such as "Reporting script", and pick when it Expires after: 30 days, 90 days, 1 year (the default) or No expiration.
  4. Under Scopes, tick only what the token needs. Quick presets fills in Read only or Full access. Scopes can't be changed later.
  5. Select Create token. The Save your token window shows it once: copy it somewhere safe, such as a password manager, then select I've saved it.

Tokens start with wlk_live_, and an account can hold 25 active tokens. In the tokens table, Rotate gives you a new token with the same name and scopes while the old one keeps working for 7 days. Revoke stops a token for good, within 30 seconds.

Scopes

write includes read. Nothing includes publish, delete or responses:read: each is granted on its own, and none is on by default.

Scope Allows
links:read Read Premium Links, Smart Links and free links
links:write Create and edit drafts
links:publish Publish, unpublish, edit anything published, create free links
links:delete Delete
forms:*, multilinks:* The same four for forms and Multilink pages
account:read Profile, allowance and usage
analytics:read Analytics
responses:read Form responses, which hold personal data people sent you

analytics:read and multilinks:read also show the names of your published links, Smart Links and forms, even without their own read scope.

Your first request

The base URL is https://api.walink.com/v1. Send the token as Authorization: Bearer <token> and request bodies as JSON. The examples read the token from a WALINK_API_TOKEN environment variable, so it stays out of your code.

List your Premium Links (needs links:read):

curl https://api.walink.com/v1/links \
  -H "Authorization: Bearer $WALINK_API_TOKEN"
{
	"data": [
		{
			"id": "lnk_3f2a9c1e-7b4d-4e8a-9f10-2c6d8e4b1a77",
			"title": "Tienda Luna orders",
			"handle": "tienda-luna",
			"plan": "chat",
			"status": "published",
			"url": "https://wa.link/tienda-luna",
			"created_at": "2026-11-05T14:32:07.000Z",
			"updated_at": "2026-11-05T14:32:07.000Z"
		}
	],
	"has_more": false,
	"next_cursor": null
}

Lists are newest first. They take limit (25 by default, 100 at most) and cursor: pass next_cursor to get the next page.

Create a draft

A create always makes a draft (needs links:write). This one opens a chat with a US number:

curl -X POST https://api.walink.com/v1/links \
  -H "Authorization: Bearer $WALINK_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: tienda-luna-promo-1" \
  -d '{
    "handle": "tienda-luna-promo",
    "plan": "chat",
    "title": "Tienda Luna promo",
    "phone": "4155550123",
    "country_code": "1",
    "country_alpha": "US",
    "message": "Hello Tienda Luna, I saw your promo"
  }'

The answer is 201 with the full record, its id and "status": "draft".

  • handle is the address after wa.link/. It can't be changed after the link is created, and a draft doesn't reserve it: the first account to publish on it gets it.
  • plan is the link type: chat, catalog, channel or group.
  • Idempotency-Key makes a retry safe for 24 hours: the same key and body return the first answer instead of a second draft.

Publish

Publishing is its own call, and it needs links:publish:

curl -X POST https://api.walink.com/v1/links/lnk_3f2a9c1e-7b4d-4e8a-9f10-2c6d8e4b1a77/publish \
  -H "Authorization: Bearer $WALINK_API_TOKEN"

Like Publish in the app, it uses one unit of your Premium Links allowance ($9 a year per link). Without a free unit the answer is 402 pool_exhausted, with the numbers in details. Add allowance on the app's Billing page (how billing works).

  • POST .../publish-check is a dry run: what still blocks the publish and how much allowance it would use.
  • POST .../unpublish takes the link offline and frees its unit. Its address stops working, printed QR codes included, and another account can then claim it.
  • PATCH /v1/links/{id} changes only the fields you send. On a published link the change is live at once, so it needs links:publish too.

Smart Links, forms and Multilink pages follow the same steps under their own paths. Smart Links use the links scopes.

/v1/free-links makes the free links every account can hold, up to 5. They work differently:

  • A free link is live the moment it's created, never a draft. That's why creating one needs links:publish, not links:write.
  • Walink picks its random address. You send a phone number or WhatsApp username, an optional message and an optional private title, which can't be changed later.
  • It can be listed, read and deleted, never edited. Its id starts with fln_, and /v1/links never shows it.
  • Editing it or seeing its analytics needs an upgrade to Premium in the app, which changes its id to lnk_.

With 5 already, a create answers 409 free_link_limit_reached, and deleting one frees its slot. More in free links.

Errors and rate limits

Every error has the same shape:

{
	"error": {
		"code": "insufficient_scope",
		"message": "This token needs the links:publish scope.",
		"param": null,
		"doc_url": "https://api.walink.com/docs#description/errors",
		"request_id": "req_4f1c9a0b7d2e4c8f9a1b3c5d7e9f0a2b",
		"details": { "required": ["links:publish"] }
	}
}
Status Common codes Meaning
401 invalid_token Missing, expired or revoked token
402 pool_exhausted, past_due_locked, subscription_required Allowance or billing, fixed in the app
403 insufficient_scope details.required names the scope
404 not_found Also for ids on other accounts
409 handle_taken, free_link_limit_reached The address is taken, or a limit is hit
422 validation_failed, handle_immutable Invalid request. details.fields lists the problems
429 rate_limited Wait Retry-After seconds
Requests Limit
Reads 120 a minute per token
Creates, edits, publishing and deletes 30 a minute per account
Analytics 10 a minute per account
Address checks 30 a minute per account

The limits are approximate, and running out of allowance is never a 429. Through the API, an account can hold up to 500 drafts per product. Every response carries a Request-Id header: quote it when you contact support.

Full reference

The same token connects AI assistants too: see Connect AI assistants.