coinfig.tax ×SixpenceX Worked example · no password Apply to partner →

Worked example · partner integration

Add a “Get your tax report” button to SixpenceX

This is the live, openly-readable walkthrough of the Coinfig partner integration. SixpenceX is a fictional exchange we use as the worked example so prospective partners can validate the whole flow — read the API, walk the handoff, send a sandbox request — before committing a single sprint.

▶ Jump to the sandbox·← Back to the partner programme

Partner (example)
SixpenceX
Method
API-key handoff
Endpoint
POST /api/v1/partner/register
Effort
~1 endpoint
What this page is

Everything below — endpoints, payloads, error states, the sandbox console — mirrors the real production integration exactly. The sandbox at the bottom sends a real request through Coinfig's proxy, which injects the SixpenceX bearer token server-side (it never reaches the browser). Real partners get the same docs under their own private URL with their own bearer and discount code wired in.

Key principle

The integration is deliberately light: one server-to-server API call followed by a redirect. No SDK, no embedded widget, no ongoing data feed for the partner to maintain. The Coinfig partner bearer token and the user's exchange API secret must never be exposed in the browser or mobile client.


How it works

SixpenceX adds a “Get your tax report” entry point — a button in the portfolio screen, a profile-menu row, or a tax-season banner. When a user opts in:

1 2 3 In SixpenceX Secure handoff Coinfig works All done Tap “Get yourtax report”. SixpenceX shares aread-only key. We import history& build the report. User lands in Coinfig,already signed in.
The whole journey, start to finish — one tap for the user, one API call for SixpenceX.
  1. User opts in inside SixpenceXThey tap “Get your tax report” and consent to share read-only history with Coinfig.
  2. SixpenceX's backend mints a read-only API keyGenerate (or reuse) a per-user API key/secret with read-only permissions scoped to transaction history.
  3. SixpenceX calls one Coinfig endpointA single POST with the user's email and those credentials, authenticated with SixpenceX's partner bearer token.
  4. Coinfig provisions the accountWe create or find the user, attach the SixpenceX data source, and begin importing transactions.
  5. Coinfig returns a passwordless sign-in linkA time-limited redirect_url comes back in the response.
  6. SixpenceX redirects the userThey land in Coinfig already signed in — no password needed on first arrival — with their history syncing in the background.
How users sign in again later

The first arrival is passwordless (a one-time sign-in link). To return afterwards the user needs a password: they can set one on that first visit when prompted, or if they skip it, sign in later via the standard “forgot password” / reset flow on their email. SSO is also supported where available.

The partner's single dependency

Your backend must be able to programmatically create (or reuse) a per-user read-only API key. Everything else is one HTTP call and a redirect.


Authentication

Coinfig issues each real partner a unique bearer token per environment. It is stored only as a SHA-256 hash on the Coinfig side and can be rotated on request. Keep it in the partner's server-side secret store.

Authorization header
Authorization: Bearer <PARTNER_TOKEN>
EnvironmentBase URL
Staginghttps://staging-api.coinfig.tax
Productionhttps://api.coinfig.tax
Token delivery

Real partner tokens are delivered through a separate secure channel — never in email and never in client code. Inject the token server-side only. The sandbox below uses the public SixpenceX bearer; it is injected by a same-origin proxy and never reaches the browser, exactly mirroring how real partner code should call this API in production.

Endpoint

POST/api/v1/partner/register
# Provisions (or finds) a Coinfig user, attaches the SixpenceX source,
# starts the import, and returns a passwordless sign-in link.
POST https://api.coinfig.tax/api/v1/partner/register
Authorization: Bearer <PARTNER_TOKEN>
Content-Type: application/json

Request

Send a JSON body. Content-Type must be application/json.

Request body
{
  "email": "user@example.com",
  "name": "Jordan",
  "surname": "Mensah",
  "partner_source": "SIXPENCE",
  "discount_code": "SIXPENCE_WELCOME_500",
  "jurisdiction": "RSA",
  "api_credentials": [
    {
      "exchange_name": "SIXPENCE",
      "api_key": "user_sixpencex_api_key",
      "api_secret": "user_sixpencex_api_secret"
    }
  ]
}

Fields

FieldRequiredNotes
emailYESValid email, max 255 chars. Identifies the Coinfig user.
namenoMax 100 chars. Pulled from the user's logged-in partner session in production.
surnamenoMax 100 chars.
partner_sourceYESMust match the partner identifier issued to you (uppercase). For this example it is SIXPENCE.
discount_codenoOptional per-partner discount applied at checkout. Issued per partner — defaults to your partner-specific code if omitted.
jurisdictionYESThe user's tax jurisdiction — send their country (ISO code or short code, e.g. RSA, USA). No fixed allow-list.
api_credentialsYES1–15 items. For SixpenceX, exchange_name must be SIXPENCE.
api_credentials[].api_keyYESMin 10 chars.
api_credentials[].api_secretYESMin 10 chars.
api_credentials[].api_passphrasenoSend only if your exchange uses a third credential.
Read-only keys

Always request API keys with read-only permission. Coinfig only reads transaction history — it never trades or withdraws. Credentials are encrypted at rest (AES-256) and decrypted only during sync.

Response

A new user returns 201 Created. An existing user returns 200 OK with the same shape and user_created: false. Sources already present return status: "skipped_duplicate".

201 Created · application/json
{
  "user_id": "usr_01HZA9F3K2WPS6T4VYXNK8B0Q1",
  "user_created": true,
  "sources_added": 1,
  "sources": [
    {
      "source_id": "src_01HZA9F3K2WPS6T4VYXNK8B0Q2",
      "exchange_name": "SIXPENCE",
      "status": "processing"
    }
  ],
  "discount_applied": true,
  "discount_code": "SIXPENCE_WELCOME_500",
  "redirect_url": "https://coinfig.tax/r/eyJhbGciOi…",
  "redirect_expires_at": "2026-07-23T08:15:00Z"
}

Fields SixpenceX should use

FieldNotes
redirect_urlOne-time, time-limited sign-in URL. Redirect the user's browser straight to this — they land signed in.
redirect_expires_atISO-8601. The link is single-use and expires after 30 days, but redirect immediately for the best experience.
sources[].statusprocessing means import is queued; skipped_duplicate means we already had that source for the user.
discount_appliedfalse means the code was rejected — see discount_error_code. Registration still succeeds.

The redirect handoff

The redirect_url is the entire handoff. You don't need to embed Coinfig or share session state — just redirect the user's browser to that URL. The link carries a signed, single-use sign-in token; Coinfig validates it and drops the user into their report area.

  • Single use. Once consumed, the URL is invalid. Generate a fresh one if you need to re-link.
  • Time-limited. Default lifetime is 30 days, but you should redirect immediately on the same request.
  • Stateful only at Coinfig. SixpenceX doesn't store the URL — it's user-facing once and then discarded.
Server-side, just before redirecting
# pseudo-code, any language
resp = post("https://api.coinfig.tax/api/v1/partner/register", ...)
redirect(resp.body.redirect_url, status=302)

Errors

StatusMeaningHow to handle
200OK · existing user, idempotent re-register.Use the returned redirect_url as you would on 201.
201Created · new user.Redirect to redirect_url.
400Validation failure (missing field, bad email, etc.).Surface the message to your support tooling; the body lists the offending field.
401Missing or invalid bearer token.Confirm the env var is set; rotate the token if it leaked.
403Bearer doesn't match the requested partner_source.Send the partner_source you were issued; don't mix tokens between partners.
409The user is already linked to a different partner.Reach out — most cases are resolvable by attaching a new source rather than re-registering.
429Rate-limited.Back off (exponential), retry. Production limits are generous for normal partner traffic.
500Server error.Retry with backoff; if persistent, contact Coinfig with the timestamp.
Discounts never block registration

Discount problems do not fail the request — the account is still created and discount_error_code / discount_message explain the issue (e.g. INVALID_DISCOUNT_CODE).

Try the sandbox

Edit the payload and hit Send request. The browser POSTs to this site's same-origin proxy, which adds the SixpenceX bearer token server-side and forwards the call to Coinfig's real partner API. The bearer never reaches the browser. The request body is exactly what a real SixpenceX backend would send.

Partner registration sandbox

POST /api/v1/partner/register

POST https://staging-api.coinfig.tax/api/v1/partner/register

Switching environments changes only the upstream URL the proxy talks to — the request body and headers are identical. Real partners get private bearer tokens for both environments; this example uses the public SixpenceX bearer for the worked walkthrough.

Use real read-only test keys to watch a sync

The placeholder credentials pass validation but won't actually sync. To watch a real import flow through end-to-end, enter genuine read-only SixpenceX (or, in a real partner integration, your exchange's) API credentials for a test account before sending.


            

Integration checklist

  1. Apply via the partner programme and receive your bearer token (staging first) from Coinfig.
  2. Store the token in the partner's server-side secret manager.
  3. Add a “Get your tax report” entry point in the partner UI.
  4. On opt-in, generate a read-only API key for that user (or reuse an existing one).
  5. Call POST /api/v1/partner/register from the partner's backend with the payload above.
  6. Redirect the user to the returned redirect_url.
  7. Test against staging end-to-end, then repeat on production with the production token.

Testing on staging

  1. Get your staging bearer from Coinfig.
  2. Send the curl below against staging.
  3. Expect 201, sources_added: 1, and a redirect_url.
  4. Open redirect_url in a browser — you should land in Coinfig signed in.
  5. Wait ~1–2 minutes; the source moves from processing to populated.
curl · staging
curl -sS -X POST https://staging-api.coinfig.tax/api/v1/partner/register \
  -H "Authorization: Bearer $PARTNER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "your-test+sixpencex@example.com",
    "partner_source": "SIXPENCE",
    "jurisdiction": "RSA",
    "api_credentials": [
      { "exchange_name": "SIXPENCE", "api_key": "<read_only_key>",
        "api_secret": "<read_only_secret>" }
    ]
  }'

Security

  • Server-to-server only — the bearer token never leaves the partner's backend.
  • Exchange API keys should be read-only; Coinfig never trades or withdraws.
  • Credentials are encrypted at rest (AES-256), decrypted only during sync.
  • Sign-in links are cryptographically signed and single-use.
  • All data access is scoped per user.
Architecture
Browser ──▶ Partner backend ──▶ Coinfig Partner API ──▶ returns redirect_url ──▶ user lands signed in
            (holds the bearer token)

OAuth 2.0 Planned · not yet available

For partners that prefer not to handle exchange API credentials, we are scoping an OAuth-style flow where the user authorises Coinfig directly with the partner — no bearer-mediated key handoff. The partner-facing API stays the same shape; only the credential exchange changes. We'll publish dates as we close out the pilot.

Talk to us

Convinced? Apply to partner via the partner programme application form. The Coinfig team reviews, sends your private docs and bearer, and a real human is on the other end if you get stuck.