{
    "info": {
        "name": "AfroPin API",
        "description": "Every endpoint in the API reference.\n\n1. Set `key_id` and `secret` (API keys in the dashboard) on the collection variables.\n2. Send requests: the collection pre-request script signs each one (X-Key-Id, X-Timestamp, X-Nonce, X-Signature) and adds a fresh Idempotency-Key.\n3. Calls that create something save the returned ID (pin_id, retail ...) into a collection variable for the next request.\n\nThe API key decides test or live mode.",
        "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
    },
    "event": [
        {
            "listen": "prerequest",
            "script": {
                "type": "text/javascript",
                "exec": [
                    "// Every request gets a fresh Idempotency-Key (max 50 characters) unless you set one on the request yourself",
                    "if (!pm.request.headers.has('Idempotency-Key')) {",
                    "    pm.request.headers.upsert({ key: 'Idempotency-Key', value: pm.variables.replaceIn('{{$guid}}') });",
                    "}",
                    "",
                    "const keyId = pm.variables.get('key_id');",
                    "const secret = pm.variables.get('secret');",
                    "if (!keyId || !secret) {",
                    "    throw new Error('Set the key_id and secret collection variables first (API keys in the dashboard).');",
                    "}",
                    "",
                    "// Canonical string: METHOD.path.timestamp.nonce.sha256(body), where path has no leading slash and no query",
                    "const url = pm.variables.replaceIn(pm.request.url.toString());",
                    "const path = url.replace(/^[a-z]+:\\/\\/[^/]+/i, '').split('?')[0].split('#')[0].replace(/^\\//, '');",
                    "// The body is resolved once and written back, so dynamic variables like {{$guid}} hash to exactly what is sent",
                    "let body = '';",
                    "if (pm.request.body && pm.request.body.mode === 'raw') {",
                    "    body = pm.variables.replaceIn(pm.request.body.raw || '');",
                    "    pm.request.body.update(body);",
                    "}",
                    "const timestamp = Math.floor(Date.now() / 1000).toString();",
                    "const nonce = pm.variables.replaceIn('{{$guid}}');",
                    "",
                    "const canonical = [",
                    "    pm.request.method.toUpperCase(),",
                    "    path,",
                    "    timestamp,",
                    "    nonce,",
                    "    CryptoJS.SHA256(body).toString(CryptoJS.enc.Hex),",
                    "].join('.');",
                    "",
                    "pm.request.headers.upsert({ key: 'X-Key-Id', value: keyId });",
                    "pm.request.headers.upsert({ key: 'X-Timestamp', value: timestamp });",
                    "pm.request.headers.upsert({ key: 'X-Nonce', value: nonce });",
                    "pm.request.headers.upsert({ key: 'X-Signature', value: CryptoJS.HmacSHA256(canonical, secret).toString(CryptoJS.enc.Hex) });"
                ]
            }
        }
    ],
    "variable": [
        {
            "key": "base_url",
            "value": "https://afropin.com/api/v1",
            "type": "string"
        },
        {
            "key": "key_id",
            "value": "",
            "type": "string"
        },
        {
            "key": "secret",
            "value": "",
            "type": "string"
        },
        {
            "key": "pin_id",
            "value": "",
            "type": "string"
        },
        {
            "key": "catalog_id",
            "value": "",
            "type": "string"
        },
        {
            "key": "webhook_id",
            "value": "",
            "type": "string"
        },
        {
            "key": "cashout_id",
            "value": "",
            "type": "string"
        },
        {
            "key": "store_id",
            "value": "",
            "type": "string"
        },
        {
            "key": "transaction_ref",
            "value": "",
            "type": "string"
        },
        {
            "key": "quote_id",
            "value": "",
            "type": "string"
        }
    ],
    "item": [
        {
            "name": "Money",
            "item": [
                {
                    "name": "Your balances",
                    "request": {
                        "method": "GET",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/wallets",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "wallets"
                            ]
                        },
                        "description": "Get the balance of each currency wallet on your account. Issuing and topping up PINs is paid from these balances.\n\nDocs: http://localhost/user/docs/reseller/wallets"
                    }
                },
                {
                    "name": "Where cards can be spent",
                    "request": {
                        "method": "GET",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/brand-stores?page=&limit=",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "brand-stores"
                            ],
                            "query": [
                                {
                                    "key": "page",
                                    "value": "",
                                    "description": "Page to return, starting at 1. Pass all to return every location without pagination.",
                                    "disabled": true
                                },
                                {
                                    "key": "limit",
                                    "value": "",
                                    "description": "Locations per page. Defaults to 20.",
                                    "disabled": true
                                }
                            ]
                        },
                        "description": "List the brand stores where your customers can redeem the PINs you sell. Use it to show customers where to spend a PIN.\n\nDocs: http://localhost/user/docs/reseller/brand-stores"
                    }
                }
            ]
        },
        {
            "name": "What you sell",
            "item": [
                {
                    "name": "Products you can sell",
                    "request": {
                        "method": "GET",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/catalog?page=&limit=",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "catalog"
                            ],
                            "query": [
                                {
                                    "key": "page",
                                    "value": "",
                                    "description": "Page to return, starting at 1. Pass all to return every product without pagination.",
                                    "disabled": true
                                },
                                {
                                    "key": "limit",
                                    "value": "",
                                    "description": "Products per page. Defaults to 20.",
                                    "disabled": true
                                }
                            ]
                        },
                        "description": "List the PIN products you are allowed to sell. Each product is a template set up for your account, with its currency, amounts, commission and cashout limits.\n\nDocs: http://localhost/user/docs/reseller/catalog"
                    }
                },
                {
                    "name": "Look up a product",
                    "request": {
                        "method": "GET",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/catalog/{{catalog_id}}",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "catalog",
                                "{{catalog_id}}"
                            ]
                        },
                        "description": "Get one of your PIN products: what it costs to issue, which amounts it accepts, and what holders can do with it.\n\nDocs: http://localhost/user/docs/reseller/catalog-item"
                    }
                }
            ]
        },
        {
            "name": "Selling PINs",
            "item": [
                {
                    "name": "Sell a PIN",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            },
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/pins",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "pins"
                            ]
                        },
                        "description": "Sell a new PIN to a customer. The face value is debited from your balance in the product currency, and the response carries the full PIN code, which is shown only here.\n\nDocs: http://localhost/user/docs/reseller/sell-pin",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"catalog_id\": \"{{catalog_id}}\",\n    \"amount\": 5000,\n    \"external_reference\": \"{{$guid}}\",\n    \"first_name\": \"Ada\",\n    \"last_name\": \"Okafor\",\n    \"email\": \"ada.okafor@example.com\",\n    \"phone_code\": \"NG\",\n    \"phone\": \"08031234567\",\n    \"webhook_id\": \"{{webhook_id}}\",\n    \"handle_delivery\": false,\n    \"wallet_links\": true\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    },
                    "event": [
                        {
                            "listen": "test",
                            "script": {
                                "type": "text/javascript",
                                "exec": [
                                    "if (pm.response.code < 300) {",
                                    "    const json = pm.response.json();",
                                    "    if (json?.data?.pin_id) pm.collectionVariables.set('pin_id', json.data.pin_id);",
                                    "}"
                                ]
                            }
                        }
                    ]
                },
                {
                    "name": "Look up a PIN",
                    "request": {
                        "method": "GET",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/pins/{{pin_id}}",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "pins",
                                "{{pin_id}}"
                            ]
                        },
                        "description": "Get a PIN you issued: its balance, status, expiry, customer and the masks of every code it has had.\n\nDocs: http://localhost/user/docs/reseller/pin"
                    }
                },
                {
                    "name": "A PIN's history",
                    "request": {
                        "method": "GET",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/pins/{{pin_id}}/movements?day=&limit=&page=",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "pins",
                                "{{pin_id}}",
                                "movements"
                            ],
                            "query": [
                                {
                                    "key": "day",
                                    "value": "",
                                    "description": "Only return transactions created on this date, for example 2026-10-27.",
                                    "disabled": true
                                },
                                {
                                    "key": "limit",
                                    "value": "",
                                    "description": "Transactions per page. Defaults to 20. Ignored when page=all.",
                                    "disabled": true
                                },
                                {
                                    "key": "page",
                                    "value": "",
                                    "description": "Page to return, starting at 1. Pass all to return every transaction without pagination.",
                                    "disabled": true
                                }
                            ]
                        },
                        "description": "List every credit and debit on a PIN, newest first: the issue, top-ups, brand redemptions and cashouts.\n\nDocs: http://localhost/user/docs/reseller/pin-movements"
                    }
                },
                {
                    "name": "Top up a PIN",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            },
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/pins/top-up",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "pins",
                                "top-up"
                            ]
                        },
                        "description": "Add value to a PIN you issued. The amount is debited from your balance and credited to the PIN.\n\nDocs: http://localhost/user/docs/reseller/top-up",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"pin_id\": \"{{pin_id}}\",\n    \"amount\": 2500,\n    \"external_reference\": \"{{$guid}}\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    }
                },
                {
                    "name": "Unfreeze a PIN",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            },
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/pins/unblock",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "pins",
                                "unblock"
                            ]
                        },
                        "description": "Re-activate a disabled PIN so it can be redeemed, topped up and cashed out again.\n\nDocs: http://localhost/user/docs/reseller/unblock",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"pin_id\": \"{{pin_id}}\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    }
                },
                {
                    "name": "Freeze a PIN",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            },
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/pins/block",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "pins",
                                "block"
                            ]
                        },
                        "description": "Freeze a PIN, for example when a customer reports it lost. A disabled PIN cannot be redeemed, topped up or cashed out until you activate it again.\n\nDocs: http://localhost/user/docs/reseller/block",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"pin_id\": \"{{pin_id}}\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    }
                },
                {
                    "name": "Give a PIN a new code",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            },
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/pins/new-code",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "pins",
                                "new-code"
                            ]
                        },
                        "description": "Give a PIN a new code when its customer has lost theirs. The PIN, its balance, expiry and history stay the same; the old code stops working straight away.\n\nDocs: http://localhost/user/docs/reseller/new-code",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"pin_id\": \"{{pin_id}}\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    }
                },
                {
                    "name": "Add to phone wallets",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            },
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/pins/wallet-links",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "pins",
                                "wallet-links"
                            ]
                        },
                        "description": "Get the links your customer opens to add a PIN to Google Wallet or Apple Wallet. The pass shows the brand, the card art, the PIN code with a QR code for the till, the balance and the expiry date, and it updates by itself.\n\nDocs: http://localhost/user/docs/reseller/wallet-links",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"pin_id\": \"{{pin_id}}\",\n    \"pin_code\": \"2923-5810-4476-1441\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    }
                },
                {
                    "name": "Change the webhook on a PIN",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            },
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/pins/webhook",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "pins",
                                "webhook"
                            ]
                        },
                        "description": "Attach a webhook to a PIN, or switch it to a different one. Later events for the PIN are sent to the new webhook.\n\nDocs: http://localhost/user/docs/reseller/pin-webhook",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"pin_id\": \"{{pin_id}}\",\n    \"webhook_id\": \"{{webhook_id}}\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    }
                },
                {
                    "name": "Choose who delivers a PIN",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            },
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/pins/delivery",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "pins",
                                "delivery"
                            ]
                        },
                        "description": "Have us deliver to a PIN's customer from now on, or stop and deliver yourself. The PIN's webhook is not changed.\n\nDocs: http://localhost/user/docs/reseller/pin-delivery",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"pin_id\": \"{{pin_id}}\",\n    \"handle_delivery\": true\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    }
                }
            ]
        },
        {
            "name": "Printed cards",
            "item": [
                {
                    "name": "Check a printed card",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            },
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/cards/lookup",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "cards",
                                "lookup"
                            ]
                        },
                        "description": "Look up one of your printed cards before activating it: the product it loads, the amounts it accepts and whether it can be activated. Nothing changes.\n\nDocs: http://localhost/user/docs/reseller/card-lookup",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"card_number\": \"9307 9280 2477 8142 827\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    }
                },
                {
                    "name": "Activate a printed card",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            },
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/cards/activate",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "cards",
                                "activate"
                            ]
                        },
                        "description": "Activate one of your printed cards for the amount the customer pays. This issues a new PIN, exactly like Issue a PIN, and retires the card number: it can never be activated or used again.\n\nDocs: http://localhost/user/docs/reseller/card-activate",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"card_number\": \"9307 9280 2477 8142 827\",\n    \"amount\": 7500,\n    \"external_reference\": \"{{$guid}}\",\n    \"first_name\": \"Amina\",\n    \"last_name\": \"Sule\",\n    \"email\": \"amina.sule@example.com\",\n    \"wallet_links\": true\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    }
                }
            ]
        },
        {
            "name": "Stores",
            "item": [
                {
                    "name": "Your stores",
                    "request": {
                        "method": "GET",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/stores?page=&limit=",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "stores"
                            ],
                            "query": [
                                {
                                    "key": "page",
                                    "value": "",
                                    "description": "Page to return, starting at 1. Pass all to return every location without pagination.",
                                    "disabled": true
                                },
                                {
                                    "key": "limit",
                                    "value": "",
                                    "description": "Locations per page. Defaults to 20.",
                                    "disabled": true
                                }
                            ]
                        },
                        "description": "List the stores and kiosks you have registered as purchase locations, in the mode of your API key.\n\nDocs: http://localhost/user/docs/reseller/stores"
                    }
                },
                {
                    "name": "Add a store",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            },
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/stores",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "stores"
                            ]
                        },
                        "description": "Register a store or kiosk where you sell PINs. Pass its ID as store_id to record which location made each sale or cashout.\n\nDocs: http://localhost/user/docs/reseller/add-store",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"title\": \"Lekki Phase 1 Kiosk\",\n    \"address\": \"14 Admiralty Way\",\n    \"latitude\": 6.4474,\n    \"longitude\": 3.4723,\n    \"country\": \"NG\",\n    \"state\": \"LA\",\n    \"city\": \"Lagos\",\n    \"postal_code\": \"106104\"\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    },
                    "event": [
                        {
                            "listen": "test",
                            "script": {
                                "type": "text/javascript",
                                "exec": [
                                    "if (pm.response.code < 300) {",
                                    "    const json = pm.response.json();",
                                    "    if (json?.data?.id) pm.collectionVariables.set('store_id', json.data.id);",
                                    "}"
                                ]
                            }
                        }
                    ]
                },
                {
                    "name": "Edit a store",
                    "request": {
                        "method": "POST",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            },
                            {
                                "key": "Content-Type",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/stores/{{store_id}}",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "stores",
                                "{{store_id}}"
                            ]
                        },
                        "description": "Replace the details of a purchase location, or switch it off. Send every field, not only the ones that change.\n\nDocs: http://localhost/user/docs/reseller/edit-store",
                        "body": {
                            "mode": "raw",
                            "raw": "{\n    \"title\": \"Lekki Phase 1 Kiosk\",\n    \"address\": \"14 Admiralty Way\",\n    \"latitude\": 6.4474,\n    \"longitude\": 3.4723,\n    \"country\": \"NG\",\n    \"state\": \"LA\",\n    \"city\": \"Lagos\",\n    \"postal_code\": \"106104\",\n    \"status\": true\n}",
                            "options": {
                                "raw": {
                                    "language": "json"
                                }
                            }
                        }
                    }
                },
                {
                    "name": "Remove a store",
                    "request": {
                        "method": "DELETE",
                        "header": [
                            {
                                "key": "Accept",
                                "value": "application/json"
                            }
                        ],
                        "url": {
                            "raw": "{{base_url}}/reseller/stores/{{store_id}}",
                            "host": [
                                "{{base_url}}"
                            ],
                            "path": [
                                "reseller",
                                "stores",
                                "{{store_id}}"
                            ]
                        },
                        "description": "Remove a purchase location. Past transactions keep their store_id.\n\nDocs: http://localhost/user/docs/reseller/remove-store"
                    }
                }
            ]
        }
    ]
}