Get started free Sign in
Theme

Build on KinCo

A REST API for managing shared ownership data programmatically. Authenticate with an API key or a session token, receive webhooks when your data changes, and integrate KinCo into your stack.

On this page

Quick start

  1. Request an API key

    Fill out the request form below and we'll set up a key for you. Keys are prefixed kinco_ and are read-only unless they have the write scope, so tell us if you need to make changes. Store your key securely.

  2. Authenticate

    Pass your key as a bearer token in every request: Authorization: Bearer kinco_…

  3. Query your data

    All endpoints live under https://api.kinco.io/api/v1 and return JSON. Lists that can grow are paginated.

Example request curl
curl https://api.kinco.io/api/v1/groups \
  -H "Authorization: Bearer kinco_your_key_here" \
  -H "Accept: application/json"
200 Response application/json
{
  "items": [
    {
      "id": "8c0f3b1e-5d2a-4f6b-9a7e-2c1d0e9f8a7b",
      "name": "Dubai Villa Partnership",
      "base_currency": "AED",
      "created_by": "3e7a9c2b-1f4d-4b8e-a6c5-0d9e8f7a6b5c",
      "created_at": "2024-09-01T10:00:00Z",
      "updated_at": "2024-09-01T10:00:00Z",
      "members": [...],
      "member_count": 3
    }
  ],
  "total": 1,
  "limit": 100,
  "offset": 0,
  "has_more": false
}

Authentication

API Key

Best for server-to-server integrations. A key acts as the user it belongs to, with that user's role in each group, and can have an expiry date. Keys are issued on request: request access.

  • read: every key can call GET endpoints. A key with no scopes is read-only.
  • write: needed for POST, PUT, PATCH and DELETE, including POSTs that only read, such as insights refresh and KinCoPilot. Without it: 403 insufficient_scope.
  • No key can use session-only endpoints, whatever its scopes: managing API keys and webhooks, billing, linking or unlinking bank connections, managing members and invitations, sending referral emails, and deleting a group or your account. Those return 403 session_required.
Authorization: Bearer kinco_…

Session (user JWT)

Best for apps acting on behalf of a signed-in user. Pass the Supabase session token in the same header. Sessions have no scopes and can use every endpoint, including the session-only ones.

Authorization: Bearer eyJ…

Role-based access

On top of the rules above, each group checks your role in it, whether you use a session or a key.

  • admin

    Everything an editor can do, plus managing members, invitations, roles and liabilities, and deleting most records.

  • editor

    Create and update assets, valuations, transactions, contributions, distributions and documents, and change group settings.

  • viewer

    Read-only access to all group data.

Deleting a group is limited to the member who created it.

Pagination

Lists that can grow (groups, assets, valuations, asset transactions, recurring transactions, contributions, distributions, settlements, ownership shares, documents and activity) return this envelope. Use the limit (default 50, 100 for groups; at most 100) and offset query params to page through them. Shorter lists, such as members, invitations, categories, liabilities, exits, connections and insights, return a plain JSON array.

Paginated list application/json
{
  "items":  [...],
  "total":  142,
  "limit":  50,
  "offset": 0,
  "has_more": true
}

Errors

Errors are JSON with a detail field. Most are a plain message; the ones you can act on in code carry an object with an error code. A 422 lists each invalid field in detail.

401 Unauthorized missing or invalid credentials
{ "detail": "Not authenticated" }     // no Authorization header
{ "detail": "Invalid API key" }       // unknown or revoked key
{ "detail": "API key expired" }
{ "detail": "Invalid token: ..." }    // expired or malformed session token
403 insufficient_scope read-only key on a write method
HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer error="insufficient_scope"

{
  "detail": {
    "error": "insufficient_scope",
    "required_scope": "write",
    "message": "This API key is read-only. Use a key with the 'write' scope to make changes."
  }
}
403 session_required any API key on a session-only endpoint
HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer error="insufficient_scope"

{
  "detail": {
    "error": "session_required",
    "message": "API keys can't use this endpoint, whatever their scopes. Sign in to KinCo to do this."
  }
}
429 rate_limited too many requests
HTTP/1.1 429 Too Many Requests
Retry-After: 30

{
  "detail": {
    "error": "rate_limited",
    "rule": "insights_refresh",
    "limit": "2 per minute",
    "retry_after": 30,
    "message": "Too many requests. Please try again in 30 seconds."
  }
}
  • Other 403s are about the group or the plan: a plain message when you aren't a member of the group or your role can't do this, and an object with "error": "upgrade_required" or "error": "limit_reached" when the plan doesn't include a feature or one of its limits is reached (for a group's data, the group owner's plan applies).
  • A 429 with "error": "quota_exceeded" means a plan quota is used up (daily AI refreshes and KinCoPilot messages, monthly PDF exports). It has no Retry-After: the quota resets at the start of the next day or month (UTC).
  • A 503 with Authentication service temporarily unavailable means we couldn't check a session token just then. Retry; you aren't signed out.

Rate limits

A limit of N per period allows a burst of N requests, then refills evenly: one more request every period ÷ N. Every authenticated request counts against its caller's limit, and the endpoints listed below also have their own.

Every request

  • Per API key

    The key's own limit: 60 unless a different limit was set for your key

    60 per minute
  • Per signed-in user

    Requests made with a session

    300 per minute
  • Per client IP

    Every request, checked before authentication

    1,200 per minute

Endpoint limits

Per user: all of your API keys and sessions share them.

  • POST /groups/{group_id}/copilot/messages 10 per minute, 100 per hour
  • POST /groups/{group_id}/insights/refresh 2 per minute, 10 per hour
  • GET /groups/{group_id}/export/portfolio-pdf 2 per minute, 10 per hour
  • POST /groups/{group_id}/connections/accounts/{account_id}/sync 1 per minute per account
  • POST /groups/{group_id}/connections/sync-all?force=true 1 per minute per group
  • Bank balance refreshes: sync, sync-all with force=true, reactivate 30 per hour, combined
  • POST /groups/{group_id}/connections/link-token 20 per hour
  • POST /groups/{group_id}/connections/exchange-token 10 per hour
  • POST /groups/{group_id}/assets/{asset_id}/valuations/sync-market 10 per minute
  • POST /groups/{group_id}/documents and documents/upload-url 30 per minute, combined
  • POST /groups/{group_id}/invitations and invitations/{invitation_id}/resend 20 per hour, 50 per day, combined
  • POST /referrals/invite 10 per hour, 30 per day

Endpoints without auth

  • GET /invitations/token/{token} 20 per minute per IP
  • GET /billing/plans 60 per minute per IP

Over a limit, the API returns 429 Too Many Requests with a Retry-After header in seconds and a rate_limited body naming the rule you hit (see Errors). Wait that long before retrying. Limits are counted on each API server separately, so you may sometimes get a little more than the stated rate; build for the numbers above.

Webhooks

KinCo sends an HTTPS POST to your endpoint when something changes in a group. Webhooks are in beta and can't be set up in the KinCo app yet. Request access, tell us the group and your HTTPS URL, and we'll set one up with you. API keys can't manage webhooks: the /webhooks endpoints are session only.

  • Each webhook belongs to one group (group_id is required) and receives only that group's events, and only while the person who registered it is an active member of the group.
  • Subscribe to the events you need, or leave events empty to receive every event, including ones added later.
  • The URL must use https and point to a public internet address. Redirects aren't followed, so register the final URL.
  • The signing secret is shown once, when the webhook is created. To rotate it, ask us to re-create the webhook.
  • A test ping sends a webhook.test event to that webhook only, at most once every 10 seconds. An account can have up to 20 webhooks.

Events

  • group.updated
  • member.joined
  • member.invited
  • asset.created
  • asset.updated
  • asset.deleted
  • valuation.created
  • valuation.updated
  • contribution.created
  • distribution.created
  • transaction.created
  • document.uploaded

Payload and headers

data is the resource as the API returns it. id identifies the event and is the same in every delivery of it, retries included.

Example delivery application/json
POST /kinco/webhooks HTTP/1.1
Content-Type: application/json
User-Agent: KinCo-Webhooks/1.0
X-KinCo-Event: asset.created
X-KinCo-Event-Id: 6f1c2d4e-8a7b-4c3d-9e2f-1a2b3c4d5e6f
X-KinCo-Signature: sha256=<hex HMAC-SHA256 of the raw body>

{
  "id": "6f1c2d4e-8a7b-4c3d-9e2f-1a2b3c4d5e6f",
  "event": "asset.created",
  "resource_type": "asset",
  "resource_id": "2b9e4c1a-7d3f-4e8b-9c6a-5f0e1d2c3b4a",
  "group_id": "8c0f3b1e-5d2a-4f6b-9a7e-2c1d0e9f8a7b",
  "data": { "id": "2b9e4c1a-...", "name": "Marina apartment", ... },
  "timestamp": "2026-10-13T12:22:05.123456+00:00"
}

Delivery and retries

  • Delivery is at least once. A failed delivery is retried with backoff, from 10 seconds up to 1 hour between attempts, for up to 24 hours. De-duplicate on the event id (also sent as X-KinCo-Event-Id).
  • Events can arrive out of order. Use timestamp, or fetch the resource, when you need its latest state.
  • Retried: no answer (connection failure or timeout), a DNS failure, and 408, 429 or any 5xx. Done: any 2xx. Any other 4xx or a 3xx isn't retried.
  • Each delivery times out after 20 seconds, and only the status code is read. Answer with a 2xx first, then process the event.
  • Retries stop if the webhook is turned off or deleted, or the person who registered it leaves the group.
  • A new webhook can miss events for up to 30 seconds after it's created, while every API server picks it up.

Verify the signature

X-KinCo-Signature is sha256= followed by the hex HMAC-SHA256 of the raw request body, keyed with your webhook's signing secret. Use the secret string as-is (don't hex-decode it). Compute it over the bytes you received, before parsing the JSON (re-serialized JSON won't match), and compare in constant time.

Node.js (Express) JavaScript
import crypto from 'node:crypto';
import express from 'express';

const app = express();
// Shown once, when you created the webhook
const secret = process.env.KINCO_WEBHOOK_SECRET;

// express.raw keeps the exact bytes KinCo signed: verify before parsing JSON
app.post('/kinco/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
  const received = Buffer.from(req.get('X-KinCo-Signature') || '');
  const expected = Buffer.from(
    'sha256=' + crypto.createHmac('sha256', secret).update(req.body).digest('hex'),
  );
  if (received.length !== expected.length || !crypto.timingSafeEqual(received, expected)) {
    return res.status(401).end();
  }

  const event = JSON.parse(req.body.toString('utf8'));
  // Retries reuse event.id (also in X-KinCo-Event-Id): skip ids you've already handled
  res.status(200).end(); // answer within 20 s, then do the work
});
Python (Flask) Python
import hashlib
import hmac
import json
import os

from flask import Flask, abort, request

app = Flask(__name__)
# Shown once, when you created the webhook
SECRET = os.environ["KINCO_WEBHOOK_SECRET"].encode()


@app.post("/kinco/webhooks")
def kinco_webhook():
    body = request.get_data()  # the raw bytes KinCo signed: verify before parsing JSON
    expected = "sha256=" + hmac.new(SECRET, body, hashlib.sha256).hexdigest()
    received = request.headers.get("X-KinCo-Signature", "")
    if not hmac.compare_digest(expected.encode(), received.encode()):
        abort(401)

    event = json.loads(body)
    # Retries reuse event["id"] (also in X-KinCo-Event-Id): skip ids you've already handled
    return "", 200  # answer within 20 s, then do the work

Endpoints

Base URL: https://api.kinco.io/api/v1. Paths below are relative to it.

Unless marked, an endpoint takes a session token or an API key. Any API key can call GET; every other method needs a key with the write scope.

Session only

Needs a signed-in session. API keys get 403 session_required, whatever their scopes.

No auth

Public: no Authorization header needed.

Groups

  • GET
    /groups

    List the groups you belong to, with their members (paginated)

  • POST
    /groups

    Create a group; you become its admin (counts toward your plan's group limit)

  • GET
    /groups/{group_id}

    Get a group with its members

  • PATCH
    /groups/{group_id}

    Update the group name or base currency (admin or editor)

  • DELETE
    /groups/{group_id} Session only

    Delete a group (only the member who created it)

Assets

  • GET
    /groups/{group_id}/assets

    List assets (paginated; filter with asset_type, search with q)

  • POST
    /groups/{group_id}/assets

    Create an asset (real_estate, bank_account, investment_account, vehicle, business, collectible, crypto, other)

  • GET
    /groups/{group_id}/assets/{asset_id}

    Get an asset with its latest valuation

  • PATCH
    /groups/{group_id}/assets/{asset_id}

    Update asset details

  • DELETE
    /groups/{group_id}/assets/{asset_id}

    Delete an asset (admin only)

  • GET
    /groups/{group_id}/assets/{asset_id}/full

    Everything about one asset in one call: metrics, valuations, transactions, contributions, distributions, ownership, members, documents, liabilities and exit

Valuations

  • GET
    /groups/{group_id}/assets/{asset_id}/valuations

    List valuations, newest first (paginated)

  • POST
    /groups/{group_id}/assets/{asset_id}/valuations

    Add a valuation (admin or editor)

  • POST
    /groups/{group_id}/assets/{asset_id}/valuations/sync-market

    Add a valuation from the current market price (assets with a ticker)

  • PATCH
    /groups/{group_id}/assets/{asset_id}/valuations/{valuation_id}

    Update a valuation (admin or editor)

  • DELETE
    /groups/{group_id}/assets/{asset_id}/valuations/{valuation_id}

    Delete a valuation (admin only)

Asset Transactions

  • GET
    /groups/{group_id}/assets/{asset_id}/transactions

    List an asset's income and expense transactions, newest first (paginated)

  • POST
    /groups/{group_id}/assets/{asset_id}/transactions

    Record a transaction (income or expense, with a category and optional splits between members)

  • GET
    /groups/{group_id}/assets/{asset_id}/transactions/summary

    Income, expenses and net operating income for the asset, by category

  • GET
    /groups/{group_id}/assets/{asset_id}/transactions/{transaction_id}

    Get one transaction

  • PATCH
    /groups/{group_id}/assets/{asset_id}/transactions/{transaction_id}

    Update a transaction

  • DELETE
    /groups/{group_id}/assets/{asset_id}/transactions/{transaction_id}

    Delete a transaction (admin only)

Categories

  • GET
    /groups/{group_id}/categories

    List the group's income and expense categories

  • POST
    /groups/{group_id}/categories

    Create a custom category (a label, and income or expense)

  • PATCH
    /groups/{group_id}/categories/{category_id}

    Rename, reorder, or turn a category on or off (its key and type can't change)

  • DELETE
    /groups/{group_id}/categories/{category_id}

    Delete a category; one still used by transactions or recurring templates is turned off instead, so past entries keep their label

Recurring Transactions

  • GET
    /groups/{group_id}/recurring-transactions

    List recurring transaction templates (paginated)

  • POST
    /groups/{group_id}/recurring-transactions

    Create a template, e.g. monthly rent; frequency is the months between occurrences (1 = monthly, 3 = quarterly, 12 = yearly)

  • GET
    /groups/{group_id}/recurring-transactions/{recurring_transaction_id}

    Get a template

  • PATCH
    /groups/{group_id}/recurring-transactions/{recurring_transaction_id}

    Update the amount, frequency or dates, or pause it with is_active

  • DELETE
    /groups/{group_id}/recurring-transactions/{recurring_transaction_id}

    Delete a template; transactions already recorded stay (admin only)

  • POST
    /groups/{group_id}/recurring-transactions/{recurring_transaction_id}/record

    Record one occurrence as a real transaction, today or on a given date (the template needs an asset)

Asset Exits

  • GET
    /groups/{group_id}/exits

    List all exited assets with realized returns in base currency

  • GET
    /groups/{group_id}/assets/{asset_id}/exit

    Get the exit record for an asset (404 if not yet exited)

  • POST
    /groups/{group_id}/assets/{asset_id}/exit

    Record an asset sale; computes net proceeds, gain or loss, CAGR, hold period and rent yield

  • DELETE
    /groups/{group_id}/assets/{asset_id}/exit

    Undo an exit (admin or editor)

Ledger

  • GET
    /groups/{group_id}/ledger

    Contributions and distributions together, with totals and a per-member breakdown

  • GET
    /groups/{group_id}/contributions

    List contributions (paginated; filter by asset, member, category or dates)

  • POST
    /groups/{group_id}/contributions

    Record a contribution

  • PATCH
    /groups/{group_id}/contributions/{contribution_id}

    Update a contribution

  • DELETE
    /groups/{group_id}/contributions/{contribution_id}

    Delete a contribution (admin only)

  • GET
    /groups/{group_id}/distributions

    List distributions (paginated; filter by asset, member or dates)

  • POST
    /groups/{group_id}/distributions

    Record a distribution

  • PATCH
    /groups/{group_id}/distributions/{distribution_id}

    Update a distribution

  • DELETE
    /groups/{group_id}/distributions/{distribution_id}

    Delete a distribution (admin only)

Settlements & Balances

  • GET
    /groups/{group_id}/balances

    Who owes whom, from expense splits and settlements (perspective=me or all)

  • GET
    /groups/{group_id}/settlements

    List recorded settlements (paginated; filter by member or dates)

  • POST
    /groups/{group_id}/settlements

    Record a settlement payment between two members to clear a balance

  • PATCH
    /groups/{group_id}/settlements/{settlement_id}

    Update a settlement's amount, currency, date or note

  • DELETE
    /groups/{group_id}/settlements/{settlement_id}

    Delete a settlement

Liabilities

  • GET
    /groups/{group_id}/liabilities

    List liabilities with their payment history

  • POST
    /groups/{group_id}/liabilities

    Create a liability (mortgage, loan, line_of_credit, other; admin only)

  • PATCH
    /groups/{group_id}/liabilities/{liability_id}

    Update a liability (admin only)

  • DELETE
    /groups/{group_id}/liabilities/{liability_id}

    Delete a liability and its payments (admin only)

  • POST
    /groups/{group_id}/liabilities/{liability_id}/payments

    Record a payment against a liability (admin only)

  • DELETE
    /groups/{group_id}/liabilities/{liability_id}/payments/{payment_id}

    Delete a payment (admin only)

Metrics & Sheets

  • GET
    /groups/{group_id}/metrics

    Portfolio metrics: active and exited assets, P&L, ownership, realized returns, performance

  • GET
    /groups/{group_id}/metrics/assets/{asset_id}

    Per-asset metrics: CAGR, ROI, equity, ownership breakdown

  • GET
    /groups/{group_id}/metrics/monthly

    A year of monthly P&L and balance sheet figures (year required; optional asset_id)

  • GET
    /groups/{group_id}/metrics/portfolio-history

    Portfolio value over time, optionally for some assets (asset_ids, comma-separated)

Ownership

  • GET
    /groups/{group_id}/assets/{asset_id}/ownership

    List ownership shares with member details (paginated)

  • PUT
    /groups/{group_id}/assets/{asset_id}/ownership

    Set an asset's ownership shares, replacing all existing ones

  • POST
    /groups/{group_id}/assets/{asset_id}/ownership/calculate

    Work out shares from contributions; a preview unless apply=true

  • DELETE
    /groups/{group_id}/assets/{asset_id}/ownership

    Delete all of an asset's ownership shares (admin only)

Members & Invitations

  • GET
    /groups/{group_id}/members

    List active members and their roles

  • PATCH
    /groups/{group_id}/members/{member_id} Session only

    Change a member's role or display name (admin only)

  • DELETE
    /groups/{group_id}/members/{member_id} Session only

    Remove a member (admin only)

  • GET
    /groups/{group_id}/invitations

    List pending invitations (invite tokens are shown only to admins using a session)

  • POST
    /groups/{group_id}/invitations Session only

    Invite someone by email (admin only)

  • POST
    /groups/{group_id}/invitations/{invitation_id}/resend Session only

    Resend an invitation email with a new token (admin only)

  • DELETE
    /groups/{group_id}/invitations/{invitation_id} Session only

    Cancel a pending invitation (admin only)

  • GET
    /invitations/pending

    List pending invitations sent to your email address

  • GET
    /invitations/token/{token} No auth

    Look up an invitation by its token: group name, role and inviter

  • POST
    /invitations/accept Session only

    Accept an invitation by token, signed in with the invited email address

Activity

  • GET
    /groups/{group_id}/activity

    The group's activity feed, newest first, with actor, resource and metadata (paginated)

Documents

  • GET
    /groups/{group_id}/documents

    List documents (paginated; filter with asset_id or group_only, search by name with q)

  • POST
    /groups/{group_id}/documents

    Upload a file as multipart form data: PDF, image, Word, Excel, PowerPoint or CSV; the size limit depends on the group's plan

  • POST
    /groups/{group_id}/documents/upload-url

    Get a signed URL to upload a large file straight to storage

  • POST
    /groups/{group_id}/documents/confirm

    After a signed-URL upload, create the document record

  • GET
    /groups/{group_id}/documents/{document_id}/download

    Get a signed URL to download a document

  • DELETE
    /groups/{group_id}/documents/{document_id}

    Delete a document and its file (admin or editor)

Export

  • GET
    /groups/{group_id}/export/sheets

    Download a year's monthly sheet as CSV: income, expenses, net operating income, contributions, distributions, total assets and equity (year required; plan feature)

  • GET
    /groups/{group_id}/export/portfolio-pdf

    Download a PDF portfolio summary (plan feature; counts toward the plan's monthly PDF exports)

AI Insights

  • GET
    /groups/{group_id}/insights

    Get AI-generated portfolio insights: cached for 12 hours, generated again when stale

  • POST
    /groups/{group_id}/insights/refresh

    Regenerate insights now: up to 8 times per group per day, and counts toward the plan's daily AI refreshes

  • PATCH
    /groups/{group_id}/insights/{insight_id}/dismiss

    Dismiss an insight so it no longer appears in the list

KinCoPilot

  • POST
    /groups/{group_id}/copilot/messages

    Send a message to KinCoPilot and get a portfolio-aware reply (plan feature, daily message quota)

Account Connections

  • POST
    /groups/{group_id}/connections/link-token Session only

    Create a link token for the bank-linking UI (Plaid)

  • POST
    /groups/{group_id}/connections/exchange-token Session only

    Exchange a public token: stores the connection and creates KinCo assets

  • GET
    /groups/{group_id}/connections

    List connections and their linked accounts

  • POST
    /groups/{group_id}/connections/accounts/{account_id}/sync

    Refresh a linked account's balance (writes a new automated valuation)

  • POST
    /groups/{group_id}/connections/sync-all

    Refresh every linked account in the group; recently synced accounts are skipped unless force=true

  • POST
    /groups/{group_id}/connections/accounts/{account_id}/link-asset

    Link a connected account to an existing KinCo asset

  • POST
    /groups/{group_id}/connections/{connection_id}/reactivate Session only

    Reactivate a connection after its bank login is re-linked

  • DELETE
    /groups/{group_id}/connections/{connection_id} Session only

    Disconnect: removes provider access but keeps KinCo assets

Webhooks

  • GET
    /webhooks Session only

    List your webhooks

  • POST
    /webhooks Session only

    Register a webhook: url, group_id (required) and events (empty for all); returns the signing secret once

  • PATCH
    /webhooks/{webhook_id} Session only

    Update the URL, events or active state

  • DELETE
    /webhooks/{webhook_id} Session only

    Delete a webhook

  • POST
    /webhooks/{webhook_id}/test Session only

    Send a webhook.test ping to this webhook only (once every 10 seconds)

API Keys

  • GET
    /api-keys Session only

    List your API keys (prefix only; secrets are never returned after creation)

  • POST
    /api-keys Session only

    Create a key: name, scopes (read, write) and an optional expires_at; returns the raw key once (up to 10 keys)

  • DELETE
    /api-keys/{key_id} Session only

    Revoke an API key immediately

Account

  • DELETE
    /users/me Session only

    Permanently delete your account: removes you from every group and cancels your invitations

Billing

  • GET
    /billing/plans No auth

    List available plans and their features

  • GET
    /billing/me

    Your plans, subscriptions and usage

  • POST
    /billing/checkout Session only

    Create a Stripe checkout session for a paid plan

  • POST
    /billing/change-plan Session only

    Upgrade or downgrade an active subscription

  • POST
    /billing/portal Session only

    Create a Stripe customer portal session to manage payment method and invoices

Referrals

  • GET
    /referrals/my-code

    Get your personal referral code (created on the first call)

  • GET
    /referrals/stats

    Referral count, tier and the people you referred

  • POST
    /referrals/invite Session only

    Send a referral invitation by email

Ready to integrate?

Request access and we'll set you up with an API key for your KinCo account.

Request API access

Tell us a bit about what you're building and we'll get you set up.