# Quickstart

import { ApiExample, ApiResponse, StagingUrl } from "../../../src/ApiExample";

Goal: in fifteen minutes, validate your key, onboard a test company and read a transaction. Everything happens on **staging**, with an `ifp_test_*` key.

## Before you start

You need a test API key, issued by Instafuel when your introducer account is opened. If you do not have one, ask your Instafuel contact — see [API keys](/en/guides/cles-api).

Keep it in an environment variable, never in your code. The staging base is <StagingUrl /> :

```bash title="Local environment"
export INSTAFUEL_API_KEY="ifp_test_9f2c4a7b1e8d3406af5b2c9d1e0f7a83"
```

<Stepper>

1. **Check your key**

   The first useful call returns your profile: it confirms the key is valid and tells you what it can do.

   <ApiExample path="/v1/papi/me" />

   <ApiResponse
     status={200}
     body={{
       ref: "APP-7C3D91B0",
       name: "Ivoire Fleet Partners",
       email: "contact@ivoirefleet.ci",
       environment: "test",
       companiesCount: 0,
       walletCreditEnabled: true,
       scopes: ["COMPANIES_READ", "TRANSACTIONS_READ", "WALLET_READ", "COMPANIES_WRITE", "CREDIT_REQUEST_WRITE", "REPORTS_READ"],
       caps: {
         perOperationFcfa: 5000000,
         dailyFcfa: 20000000,
         dailyRemainingFcfa: 20000000,
       },
     }}
   />

   `environment: "test"` confirms you are on staging. An unknown key, a revoked one, or one presented against the wrong environment gives this:

   <ApiResponse
     status={401}
     body={{
       error: {
         code: "PAPI_KEY_INVALID",
         message: "Clé d'API inconnue ou révoquée",
       },
     }}
   />

   Note that `error.message` comes back in French: it is display text produced by the API. Your logic branches on `error.code`, never on the message.

2. **Onboard a client company**

   A single call creates the company, attaches it to your portfolio, creates its fleet manager account and sends the activation link.

   <ApiExample
     method="POST"
     path="/v1/papi/companies"
     idempotency
     body={{
       name: "Transports Kouassi SARL",
       email: "contact@kouassi.ci",
       phoneNumber: "+2250700000001",
       rccm: "CI-ABJ-2024-B-12345",
       nif: "1234567A",
       headquartersAddress: "Zone 4, Marcory, Abidjan",
       fleetAdministrator: {
         firstName: "Awa",
         lastName: "Kouassi",
         email: "awa.kouassi@kouassi.ci",
         phoneNumber: "+2250700000002",
       },
     }}
   />

   <ApiResponse
     status={201}
     body={{
       id: 4832,
       ref: "ENT-B14E77A3",
       name: "Transports Kouassi SARL",
       email: "contact@kouassi.ci",
       phoneNumber: "+2250700000001",
       rccm: "CI-ABJ-2024-B-12345",
       nif: "1234567A",
       headquartersAddress: "Zone 4, Marcory, Abidjan",
       status: "ACTIVE",
       walletBalanceFcfa: 0,
       fleetAdministrator: {
         id: 9114,
         ref: "USR-2D80F5C7",
         firstName: "Awa",
         lastName: "Kouassi",
         email: "awa.kouassi@kouassi.ci",
         role: "FLEET_ADMINISTRATOR",
         status: "PENDING_ACTIVATION",
         activationExpiresAt: "2026-09-03T10:22:05.000Z",
       },
       createdAt: "2026-08-31T10:22:05.000Z",
     }}
   />

   Keep the `id`: every operation on that company uses it. The `ref` (`ENT-B14E77A3`) is the human-readable identifier to quote to support.

   A failed validation returns `422`, field by field:

   <ApiResponse
     status={422}
     body={{
       error: {
         code: "VALIDATION_ERROR",
         message: "Validation échouée",
         details: [
           {
             field: "phoneNumber",
             messages: ["Numéro ivoirien attendu, format +225XXXXXXXXXX"],
           },
           {
             field: "fleetAdministrator.email",
             messages: ["Adresse email obligatoire", "Format invalide"],
           },
         ],
       },
     }}
   />

   :::note[Attachment is not negotiable from the body]
   The company is attached to the portfolio of the key you used. An introducer identifier sent in the body is ignored, not honoured.
   :::

3. **Check your portfolio**

   <ApiExample path="/v1/papi/companies" query={{ page: 1, perPage: 20 }} />

   <ApiResponse
     status={200}
     body={{
       data: [
         {
           id: 4832,
           ref: "ENT-B14E77A3",
           name: "Transports Kouassi SARL",
           email: "contact@kouassi.ci",
           phoneNumber: "+2250700000001",
           rccm: "CI-ABJ-2024-B-12345",
           nif: "1234567A",
           headquartersAddress: "Zone 4, Marcory, Abidjan",
           status: "ACTIVE",
           walletBalanceFcfa: 0,
           createdAt: "2026-08-31T10:22:05.000Z",
         },
       ],
       pagination: {
         page: 1,
         perPage: 20,
         total: 1,
         totalPages: 1,
       },
     }}
   />

   The company you just created must show up. If your portfolio looks empty although the creation returned `201`, you are querying the other environment.

4. **Get the wallet credited**

   The balance is 0: with no credit, no fill-up is possible. You never credit directly — you declare a payment, Instafuel approves. The full flow, proof included, is in [Wallet credit](/en/guides/credit-wallet).

5. **Read transactions**

   Once the wallet is credited and a fill-up has happened at a station, the transaction is readable.

   <ApiExample
     path="/v1/papi/transactions"
     query={{ companyId: 4832, from: "2026-08-01", to: "2026-08-31" }}
   />

   <ApiResponse
     status={200}
     body={{
       data: [
         {
           ref: "TRX-4B71E0A9",
           companyId: 4832,
           station: { id: 12, name: "Station Plateau" },
           driver: { id: 3311, name: "Yao N'Guessan" },
           vehicle: { id: 812, registration: "1234 AB 01" },
           fuelType: "GASOIL",
           liters: { estimate: 42.5, actual: 42.5 },
           selfService: false,
           unitPriceFcfa: 750,
           amountFcfa: 31875,
           status: "CONFIRMED",
           createdAt: "2026-08-30T07:41:19.000Z",
           confirmedAt: "2026-08-30T07:41:19.000Z",
         },
       ],
       pagination: {
         page: 1,
         perPage: 20,
         total: 1,
         totalPages: 1,
       },
     }}
   />

   `amountFcfa` is an integer: 31,875 FCFA. Amounts never travel as decimals — only volumes (`litres`) do.

</Stepper>

## Going live

Three things change, and nothing else:

1. the base URL becomes the production one, provided with your key — see [Home](/en/accueil);
2. the key becomes `ifp_live_*`;
3. amounts are real.

Keep the two sets of variables separate in your configuration, and never run your test suite against production.

## Next

- [Authentication](/en/guides/authentification) — the exact header and its errors
- [Errors and idempotency](/en/guides/erreurs) — what to retry, when, with which key
- [Limits and quotas](/en/guides/limites-et-quotas) — pagination and rate limiting
- [API reference](/api) — the list of operations
