Finocket's developer platform lets your own products, scripts and AI tools work your books over a versioned REST API. Everything lives under Developers & API, which you reach from Settings → Developers & API - it is no longer a row in the product menu. Products, scoped API keys, OAuth clients, webhooks, payments onboarding, request logs and a live API reference all live there. Every call is workspace-scoped by row-level security.
The developer portal
Developers is one portal that works on a phone as well as a computer. A row of sections runs along the top: Start, Reference, MCP, Keys, Apps, Logs, Sandbox, Usage, Terms and Support, then the pages you already know: Payments, OAuth clients, Products, Webhooks, API docs and Environment. Every address that worked before still works.
- MCP gives you the address to point an MCP client at and a client configuration to copy. Send your key as a bearer token. A developer key gets a compact set of three tools - discover, describe and dispatch - unless you ask for the full catalogue. Your key is never filled in for you.
- Products lists the catalogue by product, generated from the Demystify integration registry, with a page per product, beside the products you register yourself.
- Apps explains app registration and review and opens the app console (see Publish an app).
Some pages need data that is not switched on yet, and they say so instead of showing a number. Developer accounts are not open, so Sandbox says a sandbox is not available yet, Usage shows nothing rather than a zero, and the MCP page does not yet list which tools your key sees. Terms says the programme terms have not been published. Support helps you prepare a written question to copy into your message; nothing is sent or saved from that page.
How do I get started with the API?
- Open Developers - the overview shows your keys, webhooks and recent API activity at a glance.
- Register a product under Developers → Products - a named container for what you're building (your app, an internal script, an AI agent). Keys and webhooks hang off it.
- Create an API key under Developers → Keys. Pick live or test mode and tick exactly the scopes it needs - from
clients:readtotally:write- nothing more. - Copy the key immediately. It is shown once, at creation, then never again. Send it as
Authorization: Bearer dmfy_live_…on every request to/api/v1/*.
Writes are idempotent where it matters: creates dedupe on your own external_id or an Idempotency-Key header, so a retried request never acts twice.
What can the API do?
The /api/v1 surface covers the whole business: clients and their ledgers, invoices (create, send, remind, PDF, payments, cancel), payments and refunds, payment links, subscriptions, expenses, items and live stock, sales and purchase orders, CRM (contacts, deals, pipelines, tasks), consent records, partner commissions - plus read-only reports: trial balance, P&L, balance sheet, ageing, GSTR-1/3B/2B/9, day book, Tally XML and more.
Two of those reads are worth knowing the shape of before you build against them. Email engagement returns opens and clicks folded into the same day-by-hour grid the report screen draws, so a dashboard you build yourself cannot disagree with the screen. Opens arrive in a field named opens_unverified, and the reason travels with them in the response rather than living only in our help pages: Apple Mail and company mail scanners fetch a tracking pixel without anyone reading the message, so an open is a hint and a click is the fact. The busiest hour is described, not recommended. No IP address is returned, because none is stored, and nothing is per-recipient - it is an aggregate.
Connected credentials answers which providers a workspace has connected, how each one was connected, whether it is verified and when it was last checked. It never returns a key, a fragment of one, its length or a fingerprint - there is no argument for another workspace, and one with nothing connected answers exactly like one that does not exist. Running several companies? Send X-Company-Id to pick one per request, or pin the key to a company at creation.
Practice records, for workspaces with the services pack switched on, are read-only: /api/v1/practice/bookings (30 days back to 30 days ahead, with each booking's status, service and the draft invoice it was billed on), /api/v1/practice/service-plans (plans and each client's sessions left) and /api/v1/practice/retainers (each retainer with its monthly schedule or deposit drawdown), on the reports:read scope. A booking names its client by id, never by name, email or phone. Billing a booking, selling a pack and starting a retainer's billing stay on the screen. While the pack is off these calls answer not found, and before its setup step they answer that the records are not available, which is different from an empty list.
How do webhooks work, and how do I verify them?
- Register an HTTPS endpoint under Developers → Webhooks and pick events -
invoice.created,payment.recorded,stock.lowand more, or all. - Finocket POSTs JSON with the event name, timestamp and data. Failed deliveries retry with exponential backoff (up to six attempts).
- Verify every delivery: read the
X-Demystify-Signatureheader (t=<timestamp>,v1=<signature>), recomputeHMAC-SHA256(secret, timestamp + "." + rawBody)with your endpoint's secret, compare in constant time, and reject stale timestamps to block replays.
Events fire however the record was written - through the API, in Finocket itself, on a phone that was offline at the time, from a bank reconciliation, from the till, or when a payment provider confirms one. So a system you have connected learns that a customer paid even when your accounts team typed it in here, which is what lets it lift a suspension on its own. A payment waiting on an approval sends nothing until it is approved; a rejected one never sends.
Developers → Webhooks also shows Recent deliveries: every event handed over, whether it arrived, what the endpoint answered, and how many attempts it took. A delivery that keeps failing stops retrying after about six hours - if the other system was down longer than that, press Resend on the row once it is back.
When should I use OAuth instead of an API key?
When a whole product - not one script - needs access. Create an OAuth2 client under Developers → OAuth clients; it uses the client-credentials grant: exchange client id and secret at POST /api/oauth/token for a short-lived bearer token carrying only the scopes you granted. Revoke the client and its tokens stop working.
Can I collect payments for my own customers?
Yes - Developers → Payments onboards sub-merchants under the aggregator model (powered by Razorpay). Register a sub-merchant, and money settles directly to their bank account - it never passes through your books or Finocket's. You get payment links and status webhooks per sub-merchant.
Where do I debug and explore?
- Developers → Logs - every API request and webhook delivery attempt, with status and timing.
- Developers → Reference - a live Swagger playground: authorize with your key and fire real requests from the browser. The OpenAPI spec is at
/api/v1/openapi.json. - Developers → API docs - the guided walkthrough, including MCP setup so AI agents (like Claude) can use your books as tools.
- Developers → Environment - the reference list of configuration names the platform uses (names only, never values).
On the phone and tablet apps these pages open in your browser rather than inside Finocket. They are built for a keyboard and a wide screen - keys, webhook URLs and request logs - so the app hands them to the browser instead of squeezing them in.
What are the inbound lead-capture webhooks?
Alongside the outbound webhooks above, Finocket exposes inbound endpoints that turn provider events into leads: telephony (calls and missed calls), inbound SMS, inbound email and WhatsApp. Each endpoint stays switched off - answering “not found” - until its token is configured; the Developers page lists the URL per channel to paste into your provider’s dashboard. See Inbox & capture for the user-side story.
What can the AI/MCP tools reach?
The MCP tool registry covers your whole business - books, GST, invoicing, inventory - and, since the growth release, the CRM chain too: leads, accounts, marketing campaigns, campaign ROI, lead funnel by source, partner earnings, team activity and activation history, plus commission-rule management. It also reads open work-in-progress per work order, and your GST notice register with how far each reply has got. Same permissions as the signed-in user; every write proposes before it commits.
With the services pack on, get_practice_bookings, get_service_plans and get_retainers give your assistant the same read-only view of bookings, service plans and retainers. There is no tool that bills or sells from them.
For outreach audits there is also list_attested_sends: the messages that went out on consent you declared rather than consent a contact recorded themselves. It answers the first question any data-protection review asks - which sends relied on an unverified claim - without reconstructing it from the message log by hand. Blocked sends on a lapsed declaration are included, because those are exactly what you want to see.
Support cases through the API and your AI assistant
Two scopes reach your workspace's support cases. With cases:read a key can list your cases and read one with its public replies and links. With cases:write it can add a public reply, link a case to an issue or a pull request, and reopen a case that was released or is waiting on you, for example when a fix did not hold. Every other status move is made by our support team, and a key can never close, decline or mark a case as a duplicate: those stay human decisions.
What comes back is masked. Reporter names, email addresses and phone numbers are never returned, and neither are internal notes. Your AI assistant gets the same abilities through the MCP tools, with the same limits: it can list and read your cases, reply, link and reopen, and it can never close one. These two scopes are not on the Keys screen's list of boxes yet. Until cases are switched on for your workspace, these calls answer that cases are not available yet.
What the tools deliberately cannot do
Some things are reachable in the app and are not exposed as tools, on purpose - because a tool call has no confirm card and no named human behind it:
- Approving anything an assistant drafted. Growth-agent campaigns and GST notice replies are approved in the app, by a person. A tool would put a model on both sides of that review.
- Changing how much an assistant may do unattended. The autonomy setting is not tool-reachable, so an agent cannot widen its own limits.
- Committing a Tally import, or undoing a completed action. Both are large writes that exist behind a review step. Exporting to Tally is exposed, because it changes nothing.
- Your personal tax figures. API keys carry business scopes, and there is no tax scope - so your rent, premiums and investment rows are never reachable with a key issued for the books. Ask Mysty inside the app instead.
Nothing here files a return, moves money, or sends a message without the same consent and quiet-hours checks the rest of Finocket applies.
Related: Modules & plans, Usage & activity.
Why doesn't my counter-sales total match the till's Z-report?
It should, and now it does - but only if you add up the right column. A refund at the counter is a credit note, and a credit note carries a positive total, because that is what the document says: it is a real credit for a real amount. It also carries the terminal of the bill it reverses, so it appears in /v1/pos/sales alongside the sales.
So every row carries two fields you should read together. direction is "sale" or "return", and signed_total is the same money with that direction applied - negative for a return. Sum signed_total, never total. Summing total adds refunds to takings instead of subtracting them, so a day is overstated by twice what you refunded.
Cancelled bills are not in the list at all. An exchange that fails part-way cancels its credit note rather than deleting it, so the trail survives - but a reversal that never happened is not money, on this list or on the Z-report. Drafts are excluded for the same reason: nothing was rung up.
Filter by from, to and terminal_id for a date range at one till. For a single register session, take the rows whose cash_session_id is that session: their signed_total adds up to exactly the net figure the Z-report shows for it. The two are built from one definition of what a counter sale is, so they cannot drift apart.
My key was refused. Do I need to upgrade?
Not necessarily, and the response tells you which of three things happened rather than making you guess. All three are a 403, and they need three different fixes.
- The key was never given that scope. The message names the missing scope. Fix it by issuing a new key with the right scopes ticked - scopes cannot be added to a key after it is made.
- The plan no longer includes that area. The error code is
plan_upgrade_requiredand the message names the area. The key is fine; the workspace moved to a plan that does not carry it. Changing plan restores it. - An administrator switched that area off for the workspace. The code is the plain
forbiddenand the message says so: no plan change lifts this. Buying a bigger plan will not help, and we will not suggest it. Ask whoever administers the workspace to switch the area back on.
A workspace owner simply hiding an area from their own menu does not refuse your key. Tidying a menu and cutting off an integration are different acts, and only the second one is deliberate.
The AI/MCP tools answer the same way, in the same three flavours, for the same reasons - so a tool call and a REST call cannot disagree about whether you are allowed in.
Paise or rupees?
Money fields are not all the same unit, and getting it backwards overstates an amount a hundredfold. The reference states, in one place, which fields are whole paise and which are rupees - check it before you write the first integer.
The reference is checked against the API itself on every build, address by address and call by call. A call shipped without documentation, or documented without being shipped, stops the build rather than reaching you.