Skip to content

Registering

All of this happens at id.costia.app/developer, with your own Costia account. There is no human review.

The name you choose is what your customer sees on the consent screen, next to “wants to access your Costia account”. Use the one they know you by: it is the only thing they have to go on when deciding whether to authorise you.

You can register up to ten partners per account.

Only if you are going to write invoices. Signing in does not need it.

When you claim a domain you get a token, and you publish it one of two ways:

DNS record
_costia-challenge.yourshop.com TXT costia-verify-xxxxxxxxxxxx
Or a file on your site
https://yourshop.com/.well-known/costia-partner

The file’s content is the token, verbatim. Then you press verify.

Either one is enough. The check runs over HTTPS only, does not follow redirects and rejects private addresses — so a domain pointing at your internal network does not count as proof.

Once verified, your brand is pinned to what you proved, not to what you typed. That is what unlocks invoices:write.

On the consent screen, Costia shows every actual redirect domain used by the client. It gets a Verified badge only when it matches a domain you proved or one of its subdomains; every other domain gets an Unverified badge. Proving one domain does not lend trust to a redirect URL hosted somewhere else.

You need two things.

The client name, which is what people read on the consent screen.

The redirect URLs, which your framework decides, not you. With Better Auth it is https://your-domain/api/auth/callback/costia; with NextAuth, /api/auth/callback/costia; with Spring Security, /login/oauth2/code/costia. They must match character for character, with no wildcards or fragments. Server clients use https. A public native application may also use a reverse-domain private scheme such as com.yourshop.app:/oauth2redirect. If it does not match, authorization is rejected before it starts: this stops a third party receiving the code in your name.

Choose confidential when the client runs on a server that can protect credentials. You receive a client_id and client_secret. Choose public for an installed application: it receives only a client_id and authenticates with PKCE, because a secret embedded in a binary can be extracted and is not a secret.

A public client cannot request invoices:write: anybody can imitate its client_id, so Costia cannot let it write invoices under a verified brand. It also receives no refresh token and cannot request offline_access; it repeats authorization when access is needed again. Client type is immutable after creation: create a new client to migrate between public and confidential.

You can list every client_id, edit the name, scopes and multiple exact login redirect URLs, add post-logout redirect URLs, rotate the secret, or delete the client. Costia’s OIDC end-session endpoint is https://id.costia.app/connect/logout.

Ask only for what you will use. Your customer can uncheck any of them except identification, and if they uncheck one they are told explicitly what your application will no longer be able to do.

Scope What for Requirement
openid Identify the account. Always present
profile Read their name
email Read their verified email That exact address must be verified
invoices:read Read their invoices
invoices:write Write invoices in your name Verified domain
offline_access Keep working when they are not present Confidential client only

invoices:read and invoices:write are independent, not a ladder. A shop writes and never reads; an accountant reads and never writes. Granting both is an explicit decision.

Asking for invoices:write without a verified domain is rejected when you create the client, not when you use it — a client that never received the permission cannot ask for it later.

Any enabled scope can be marked mandatory. It still starts unchecked: the person has to grant it deliberately, but cannot continue without it. If email is mandatory and the address is unverified, Costia asks them to sign in with Google or Apple using that exact address, or send a single-use link when outbound email is configured for the environment. The link expires, is delivery-rate-limited, and verifies only the exact address it was sent to. Apple only counts when it actually supplies the email; one entered manually afterwards is not verified. Every authorization request must include all scopes you configured as mandatory; Costia never silently expands the permissions requested by the client.

You can also suggest a default grant duration. The person can always change the date or choose no expiry. Once expired, the application has to ask again.