> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chargerdojo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Let a partner register with you

> Issue a registration token so a partner's OCPI client can run the credentials handshake against you, and see the connection appear once they do.

[Connecting a partner endpoint](/guide/connect-a-partner) covers the direction most people
start with: you hold their token, and you drive the handshake. This page is the other one.
Here **they** drive it. You hand out a registration token, they POST their credentials to
you, and a connection appears once they have.

You need this when your partner wants to prove their client works, not their server. It is
also the direction to use when a partner asks you for Token A: in OCPI the receiving party
issues it, so if they are asking, they mean to register into you.

## Issue a token

In the tester, open **Endpoints** and switch the direction to **They register**. Pick the
OCPI version they run and issue a token. The picker offers 2.1.1, 2.2.1 and 2.3.0, which is
the same set every other version picker in the tester offers.

Pick the version they actually run, not the newest one. The token is recorded against that
version, and a client that speaks a different one will not finish the handshake against it.

You get four values. Send all four, together, over whatever channel you already use with
that partner. The specification puts this exchange deliberately outside the protocol, so
there is no OCPI-blessed way to deliver them.

| Value              | What they do with it                                              |
| ------------------ | ----------------------------------------------------------------- |
| Registration token | Their `Authorization` header, on every request in the handshake.  |
| Versions URL       | Where their client starts: it lists the versions we serve.        |
| OCPI version       | The one you issued for. It has to match what their client speaks. |
| Our party          | The `country_code` and `party_id` they address us as.             |

## How they send the token

This is the step that goes wrong, and it goes wrong silently.

The credentials token is transported differently across versions. On 2.1.1 it goes in the
header as it is; from 2.2 onwards the header carries the Base64 of it. The issued-token
panel shows the exact header for both forms, so you can paste the one they need rather than
describe it.

Expect the field to disagree with the document here. The specification itself notes that
many 2.1.1 and 2.2 implementations do not encode the token, and tells implementations that
want to interoperate with them to handle both by "trial and error or configuration flags".
Encoding has been required since 2.2-d2 regardless.

We hold the line: an unencoded value on a 2.2 or later endpoint stays a `401`. Accepting it
would tell you a partner is conformant when the specification says they are not, and that is
the one thing this tool must not do.

<Note>
  When the token is right and only the encoding is wrong, the connection says exactly that,
  so a `401` on a partner's first call is one line to send them rather than a credential hunt.
</Note>

## What happens when they register

Their client reads the versions URL, picks its version, and POSTs its credentials to our
credentials endpoint. We then call **back** to their versions URL with the token they just
sent, read their endpoints, and only then record the registration. That callback is part of
the handshake, so their endpoint has to be reachable from the internet for it to finish. If
it runs on a laptop or inside a VPC, [put a tunnel in front of it](/guide/connect-a-local-endpoint).

The row reads **Waiting for them** until their POST arrives, which means the token is issued
and unused and nothing is due from you, then **Registered** once the handshake finishes and
they hold a live credentials token. Until it does we do not know who they are, so the row
shows no party. That is the expected state, not a stuck one.

## Reading the token back, and taking it away

While a row is still waiting, **Show token** returns the registration token you issued, so
you do not have to keep a copy somewhere less safe than we keep it. Once they register, the
handshake has spent that token and there is nothing left to show. Their system now holds its
own credentials token instead.

**Revoke** ends the registration in both directions: we tell them their credentials are
invalid, then invalidate ours. After that their system can no longer reach you, and getting
back means issuing a fresh token for them to register with again.

Revoking is a protocol act, not a tidy-up, which is why a live inbound row cannot simply be
deleted. Removing the row on its own would leave their client holding a token it believes
still works. Revoke first; then the row can be removed.

## What counts against your plan

An inbound connection is a connection. Inbound and outbound rows share one ceiling, so
three registrations from partners and three endpoints you added are six against the same
limit. Revoking does not free the slot on its own, because the row survives holding
nothing: remove the row when you are finished with it.

## Next

[Run a conformance suite](/guide/run-a-suite) against them once the row says registered, or
[run a charging journey](/guide/run-a-charging-journey) if you want a timed end-to-end flow
rather than module-by-module checks.
