Skip to content

Getting started with the API

The TAYO.pro API gives your own software access to your projects, quotes, invoices and reminders. It is meant to be called by a server, never from a browser: an API key in a JavaScript bundle is a published key.

The API is a paid add-on on top of a PLUS subscription. Without it, every call answers 403 addon_required.

Keys are created from Settings → API, and only an administrator can do it.

Every company gets two keys, and the prefix decides everything:

Key What it does
tay_live_… Acts on your real data.
tay_test_… Runs a request through the whole chain, then returns a sample response without touching anything.

The mode therefore appears neither in the URL, nor in the body, nor in a header — only in the key you present.

The key goes in the Authorization header and nowhere else — a key passed as a query parameter is refused with a 401, even when it is valid.

Fenêtre de terminal
curl https://staging.tayo.pro/api/v1/ping \
-H "Authorization: Bearer tay_live_your_key"

The base URL is https://staging.tayo.pro/api/v1.

A request presented with a tay_test_… key goes through exactly the same chain as a real one: authentication, quota accounting, and the same validation of body and parameters. Then it stops before the business logic.

In practice, in test mode:

  • nothing is written and nothing is deleted;
  • no email, no PDF and no call to Tayo is triggered;
  • the response conforms to the production response schema;
  • ids are stable between calls — prj_test_1 stays prj_test_1 — so your tests can assert against them.

That is what makes going live uneventful: you have already seen the exact shape of every response.

Forcing an error case with Tay-Test-Scenario

Section titled “Forcing an error case with Tay-Test-Scenario”

A serious integrator needs to exercise their error branches. The Tay-Test-Scenario header picks the response test mode should return:

Scenario What you get
success The nominal case. This is the default.
not_found The requested resource does not exist.
validation_error The body is refused, with per-field detail.
send_failed Sending to the client failed.
quota_exceeded Your monthly quota is spent.

Each endpoint accepts a subset of these — send_failed is meaningless on a read. A value outside that subset answers 400.

Swap the key. That is all.

URLs, request bodies, response schemas and error codes are identical in both modes — that is the entire point of test mode.

Every failing request returns the same envelope:

{
"error": {
"code": "invalid_argument",
"message": "The request failed validation.",
"details": [
{ "field": "amount", "code": "invalid_type", "message": "Expected number" }
]
}
}

details is present only on a validation error.

Status code When
400 invalid_argument The request failed validation.
400 failed_precondition The operation is impossible in the current state.
400 test_header_in_live_mode Tay-Test-Scenario was sent with a live key.
401 unauthenticated Key missing, revoked, or presented another way.
403 permission_denied This key may not perform this action.
403 addon_required The API add-on is not active on the company.
404 not_found The resource does not exist.
409 already_exists The resource already exists.
409 delivery_in_flight The webhook delivery is already queued for another attempt.
409 endpoint_deleted The endpoint this delivery was sent to no longer exists.
409 endpoint_disabled The endpoint this delivery was sent to is disabled.
409 retry_limit_reached The delivery has reached its manual retry limit.
429 rate_limited Too many requests per minute — slow down and retry. See Usage limits.
429 quota_exceeded The monthly quota and its overage allowance are spent. See Usage limits.
500 internal An error on our side.
503 unavailable Temporarily unavailable.

Messages are English only, and will stay that way: a program reads the code, and translating the prose would only make what it greps for harder to find.

If a response departs from what the reference describes, that is a bug and fixing it is included in the add-on: see Support.